fix build_netmask to treat the count as a prefix and add tests

This commit is contained in:
arvidn 2020-01-06 10:57:34 +01:00 committed by Arvid Norberg
parent af3d084092
commit 96695fa714
4 changed files with 114 additions and 72 deletions

View File

@ -74,6 +74,15 @@ namespace libtorrent {
// internal
inline address_v6 make_address_v6(string_view str, boost::system::error_code& ec)
{ return address_v6::from_string(str.data(), ec); }
// internal
inline address make_address(string_view str)
{ return address::from_string(str.data()); }
// internal
inline address_v4 make_address_v4(string_view str)
{ return address_v4::from_string(str.data()); }
// internal
inline address_v6 make_address_v6(string_view str)
{ return address_v6::from_string(str.data()); }
#endif
}

View File

@ -89,6 +89,11 @@ namespace libtorrent {
TORRENT_EXTRA_EXPORT bool match_addr_mask(address const& a1
, address const& a2, address const& mask);
// return a netmask with the specified address family and the specified
// number of prefix bit set, of the most significant bits in the resulting
// netmask
TORRENT_EXTRA_EXPORT address build_netmask(int bits, int family);
// returns true if the specified address is on the same
// local network as us
TORRENT_EXTRA_EXPORT bool in_local_network(io_service& ios, address const& addr

View File

@ -165,48 +165,6 @@ namespace {
);
}
#if TORRENT_USE_GETIPFORWARDTABLE || TORRENT_USE_NETLINK
address build_netmask(int bits, int const family)
{
if (family == AF_INET)
{
address_v4::bytes_type b;
b.fill(0xff);
for (int i = int(b.size()) - 1; i >= 0; --i)
{
if (bits < 8)
{
b[std::size_t(i)] <<= bits;
break;
}
b[std::size_t(i)] = 0;
bits -= 8;
}
return address_v4(b);
}
else if (family == AF_INET6)
{
address_v6::bytes_type b;
b.fill(0xff);
for (int i = int(b.size()) - 1; i >= 0; --i)
{
if (bits < 8)
{
b[std::size_t(i)] <<= bits;
break;
}
b[std::size_t(i)] = 0;
bits -= 8;
}
return address_v6(b);
}
else
{
return address();
}
}
#endif
#if TORRENT_USE_NETLINK
int read_nl_sock(int sock, span<char> buf, std::uint32_t const seq, std::uint32_t const pid)
@ -353,36 +311,7 @@ namespace {
return false;
ip_info->preferred = (addr_msg->ifa_flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED | IFA_F_TENTATIVE)) == 0;
if (addr_msg->ifa_family == AF_INET6)
{
TORRENT_ASSERT(addr_msg->ifa_prefixlen <= 128);
if (addr_msg->ifa_prefixlen > 0)
{
address_v6::bytes_type mask = {};
auto it = mask.begin();
if (addr_msg->ifa_prefixlen > 64)
{
detail::write_uint64(0xffffffffffffffffULL, it);
addr_msg->ifa_prefixlen -= 64;
}
if (addr_msg->ifa_prefixlen > 0)
{
std::uint64_t const m = ~((1ULL << (64 - addr_msg->ifa_prefixlen)) - 1);
detail::write_uint64(m, it);
}
ip_info->netmask = address_v6(mask);
}
}
else
{
TORRENT_ASSERT(addr_msg->ifa_prefixlen <= 32);
if (addr_msg->ifa_prefixlen != 0)
{
std::uint32_t const m = ~((1U << (32 - addr_msg->ifa_prefixlen)) - 1);
ip_info->netmask = address_v4(m);
}
}
ip_info->netmask = build_netmask(addr_msg->ifa_prefixlen, addr_msg->ifa_family);
ip_info->interface_address = address();
int rt_len = int(IFA_PAYLOAD(nl_hdr));
@ -492,8 +421,47 @@ int _System __libsocket_sysctl(int* mib, u_int namelen, void *oldp, size_t *oldl
}
#endif
void build_netmask_impl(span<unsigned char> mask, int prefix_bits)
{
TORRENT_ASSERT(prefix_bits <= mask.size() * 8);
int i = 0;
while (prefix_bits >= 8)
{
mask[i] = 0xff;
prefix_bits -= 8;
++i;
}
if (i < mask.size())
{
mask[i] = (0xff << (8 - prefix_bits)) & 0xff;
++i;
while (i < mask.size())
{
mask[i] = 0;
++i;
}
}
}
} // <anonymous>
address build_netmask(int prefix_bits, int const family)
{
if (family == AF_INET)
{
address_v4::bytes_type b;
build_netmask_impl(b, prefix_bits);
return address_v4(b);
}
else if (family == AF_INET6)
{
address_v6::bytes_type b;
build_netmask_impl(b, prefix_bits);
return address_v6(b);
}
return {};
}
// return (a1 & mask) == (a2 & mask)
bool match_addr_mask(address const& a1, address const& a2, address const& mask)
{

View File

@ -104,3 +104,63 @@ TORRENT_TEST(is_ip_address)
TEST_EQUAL(is_ip_address("::1"), true);
TEST_EQUAL(is_ip_address("2001:db8:85a3:0:0:8a2e:370:7334"), true);
}
TORRENT_TEST(build_netmask_v4)
{
TEST_CHECK(build_netmask(0, AF_INET) == make_address("0.0.0.0"));
TEST_CHECK(build_netmask(1, AF_INET) == make_address("128.0.0.0"));
TEST_CHECK(build_netmask(2, AF_INET) == make_address("192.0.0.0"));
TEST_CHECK(build_netmask(3, AF_INET) == make_address("224.0.0.0"));
TEST_CHECK(build_netmask(4, AF_INET) == make_address("240.0.0.0"));
TEST_CHECK(build_netmask(5, AF_INET) == make_address("248.0.0.0"));
TEST_CHECK(build_netmask(6, AF_INET) == make_address("252.0.0.0"));
TEST_CHECK(build_netmask(7, AF_INET) == make_address("254.0.0.0"));
TEST_CHECK(build_netmask(8, AF_INET) == make_address("255.0.0.0"));
TEST_CHECK(build_netmask(9, AF_INET) == make_address("255.128.0.0"));
TEST_CHECK(build_netmask(10, AF_INET) == make_address("255.192.0.0"));
TEST_CHECK(build_netmask(11, AF_INET) == make_address("255.224.0.0"));
TEST_CHECK(build_netmask(22, AF_INET) == make_address("255.255.252.0"));
TEST_CHECK(build_netmask(23, AF_INET) == make_address("255.255.254.0"));
TEST_CHECK(build_netmask(24, AF_INET) == make_address("255.255.255.0"));
TEST_CHECK(build_netmask(25, AF_INET) == make_address("255.255.255.128"));
TEST_CHECK(build_netmask(26, AF_INET) == make_address("255.255.255.192"));
TEST_CHECK(build_netmask(27, AF_INET) == make_address("255.255.255.224"));
TEST_CHECK(build_netmask(28, AF_INET) == make_address("255.255.255.240"));
TEST_CHECK(build_netmask(29, AF_INET) == make_address("255.255.255.248"));
TEST_CHECK(build_netmask(30, AF_INET) == make_address("255.255.255.252"));
TEST_CHECK(build_netmask(31, AF_INET) == make_address("255.255.255.254"));
TEST_CHECK(build_netmask(32, AF_INET) == make_address("255.255.255.255"));
}
TORRENT_TEST(build_netmask_v6)
{
TEST_CHECK(build_netmask(0, AF_INET6) == make_address("::"));
TEST_CHECK(build_netmask(1, AF_INET6) == make_address("8000::"));
TEST_CHECK(build_netmask(2, AF_INET6) == make_address("c000::"));
TEST_CHECK(build_netmask(3, AF_INET6) == make_address("e000::"));
TEST_CHECK(build_netmask(4, AF_INET6) == make_address("f000::"));
TEST_CHECK(build_netmask(5, AF_INET6) == make_address("f800::"));
TEST_CHECK(build_netmask(6, AF_INET6) == make_address("fc00::"));
TEST_CHECK(build_netmask(7, AF_INET6) == make_address("fe00::"));
TEST_CHECK(build_netmask(8, AF_INET6) == make_address("ff00::"));
TEST_CHECK(build_netmask(9, AF_INET6) == make_address("ff80::"));
TEST_CHECK(build_netmask(10, AF_INET6) == make_address("ffc0::"));
TEST_CHECK(build_netmask(11, AF_INET6) == make_address("ffe0::"));
TEST_CHECK(build_netmask(119, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fe00"));
TEST_CHECK(build_netmask(120, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"));
TEST_CHECK(build_netmask(121, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80"));
TEST_CHECK(build_netmask(122, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffc0"));
TEST_CHECK(build_netmask(123, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0"));
TEST_CHECK(build_netmask(124, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"));
TEST_CHECK(build_netmask(125, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8"));
TEST_CHECK(build_netmask(126, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"));
TEST_CHECK(build_netmask(127, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"));
TEST_CHECK(build_netmask(128, AF_INET6) == make_address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
}
TORRENT_TEST(build_netmask_unknown)
{
TEST_CHECK(build_netmask(0, -1) == address{});
}