forked from Mirrors/openclonk
Rank private/UL addresses lower than global ones
Also adds some tests. Yay tests!alut-include-path
parent
d7e71d8362
commit
3ebedd0c5f
|
@ -273,6 +273,25 @@ bool C4NetIO::HostAddress::IsLocal() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool C4NetIO::HostAddress::IsPrivate() const
|
||||||
|
{
|
||||||
|
// IPv6 unique local address
|
||||||
|
if (gen.sa_family == AF_INET6)
|
||||||
|
return (v6.sin6_addr.s6_addr[0] & 0xfe) == 0xfc;
|
||||||
|
if (gen.sa_family == AF_INET)
|
||||||
|
{
|
||||||
|
uint32_t addr = ntohl(v4.sin_addr.s_addr);
|
||||||
|
uint32_t s = (addr >> 16) & 0xff;
|
||||||
|
switch (addr >> 24)
|
||||||
|
{
|
||||||
|
case 10: return true;
|
||||||
|
case 172: return s >= 16 && s <= 31;
|
||||||
|
case 192: return s == 168;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
|
|
@ -113,7 +113,8 @@ public:
|
||||||
bool IsNull() const;
|
bool IsNull() const;
|
||||||
bool IsMulticast() const;
|
bool IsMulticast() const;
|
||||||
bool IsLoopback() const;
|
bool IsLoopback() const;
|
||||||
bool IsLocal() const;
|
bool IsLocal() const; // IPv6 link-local address
|
||||||
|
bool IsPrivate() const; // IPv6 ULA or IPv4 private address range
|
||||||
// bool IsBroadcast() const;
|
// bool IsBroadcast() const;
|
||||||
|
|
||||||
StdStrBuf ToString(int flags = 0) const;
|
StdStrBuf ToString(int flags = 0) const;
|
||||||
|
|
|
@ -217,7 +217,7 @@ static void SortAddresses(std::vector<C4Network2Address>& addrs)
|
||||||
bool haveIPv6 = false;
|
bool haveIPv6 = false;
|
||||||
for (auto& addr : localAddrs)
|
for (auto& addr : localAddrs)
|
||||||
{
|
{
|
||||||
if (addr.GetFamily() == C4NetIO::HostAddress::IPv6 && !addr.IsLocal())
|
if (addr.GetFamily() == C4NetIO::HostAddress::IPv6 && !addr.IsLocal() && !addr.IsPrivate())
|
||||||
{
|
{
|
||||||
haveIPv6 = true;
|
haveIPv6 = true;
|
||||||
break;
|
break;
|
||||||
|
@ -235,13 +235,17 @@ static void SortAddresses(std::vector<C4Network2Address>& addrs)
|
||||||
case C4NetIO::HostAddress::IPv6:
|
case C4NetIO::HostAddress::IPv6:
|
||||||
if (addr.IsLocal())
|
if (addr.IsLocal())
|
||||||
rank = 100;
|
rank = 100;
|
||||||
|
else if (addr.IsPrivate())
|
||||||
|
rank = 150;
|
||||||
else if (haveIPv6)
|
else if (haveIPv6)
|
||||||
// TODO: Rank public IPv6 addresses by longest matching prefix with local addresses.
|
// TODO: Rank public IPv6 addresses by longest matching prefix with local addresses.
|
||||||
rank = 300;
|
rank = 300;
|
||||||
break;
|
break;
|
||||||
case C4NetIO::HostAddress::IPv4:
|
case C4NetIO::HostAddress::IPv4:
|
||||||
// TODO: Maybe rank IPv4 addresses from private address ranges differently.
|
if (addr.IsPrivate())
|
||||||
rank = 200;
|
rank = 150;
|
||||||
|
else
|
||||||
|
rank = 200;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(!"Unexpected address family");
|
assert(!"Unexpected address family");
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* OpenClonk, http://www.openclonk.org
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017, The OpenClonk Team and contributors
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the ISC license; see accompanying file
|
||||||
|
* "COPYING" for details.
|
||||||
|
*
|
||||||
|
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
||||||
|
* See accompanying file "TRADEMARK" for details.
|
||||||
|
*
|
||||||
|
* To redistribute this file separately, substitute the full license texts
|
||||||
|
* for the above references.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <C4Include.h>
|
||||||
|
#include "network/C4NetIO.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
class C4NetIOTest : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
C4NetIOTest()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_WINSOCK
|
||||||
|
AcquireWinSock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~C4NetIOTest()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_WINSOCK
|
||||||
|
ReleaseWinSock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(C4NetIOTest, HostAddressCategories)
|
||||||
|
{
|
||||||
|
static struct TestAddr
|
||||||
|
{
|
||||||
|
const char *addr;
|
||||||
|
bool null, multicast, loopback, linklocal, priv;
|
||||||
|
} addrs[] =
|
||||||
|
{
|
||||||
|
// null mc loopb ll priv
|
||||||
|
{"0.0.0.0", true, false, false, false, false},
|
||||||
|
{"192.168.0.1", false, false, false, false, true},
|
||||||
|
{"10.168.0.1", false, false, false, false, true},
|
||||||
|
{"172.16.10.1", false, false, false, false, true},
|
||||||
|
{"127.0.0.1", false, false, true, false, false},
|
||||||
|
{"239.1.1.1", false, true, false, false, false},
|
||||||
|
|
||||||
|
// null mc loopb ll priv
|
||||||
|
{"::", true, false, false, false, false},
|
||||||
|
{"::1", false, false, true, false, false},
|
||||||
|
{"ff02::1", false, true, false, false, false},
|
||||||
|
{"ff15::1234", false, true, false, false, false},
|
||||||
|
{"fe80::1234:abcd:def:1234", false, false, false, true, false},
|
||||||
|
{"fe80::1234:abcd:def:1234", false, false, false, true, false},
|
||||||
|
{"fd12::1234:abcd:def:1234", false, false, false, false, true},
|
||||||
|
{"fc12::1234:abcd:def:1234", false, false, false, false, true},
|
||||||
|
|
||||||
|
{nullptr, false, false, false, false, false},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto t = addrs; t->addr; t++)
|
||||||
|
{
|
||||||
|
// TODO: While this produces better error messages than EXPECT_EQ, failures are still super confusing.
|
||||||
|
auto check = [&](bool a, bool b)
|
||||||
|
{
|
||||||
|
if (a == b)
|
||||||
|
return ::testing::AssertionSuccess();
|
||||||
|
else
|
||||||
|
return ::testing::AssertionFailure() << "addr = " << t->addr << " expected: " << b;
|
||||||
|
};
|
||||||
|
C4NetIO::HostAddress addr(StdStrBuf(t->addr));
|
||||||
|
EXPECT_TRUE(check(addr.IsNull(), t->null));
|
||||||
|
EXPECT_TRUE(check(addr.IsMulticast(), t->multicast));
|
||||||
|
EXPECT_TRUE(check(addr.IsLoopback(), t->loopback));
|
||||||
|
EXPECT_TRUE(check(addr.IsLocal(), t->linklocal));
|
||||||
|
EXPECT_TRUE(check(addr.IsPrivate(), t->priv));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue