Move IPRange out of net.hpp; free up TruncateV6 etc.

- Move IPRange into its own net/ip_range.hpp

- Move the static net::IPPacket::TruncateV6, etc. functions to free
net::TruncateV6, etc. functions (now from net/ip.hpp instead of
net/ip_packet.hpp).

- Make net::TruncateV6 and net::ExpandV4 constexpr.

- Add IPRange::FromIPv4 factory function (to replace the iprange_ipv4
free function)
This commit is contained in:
Jason Rhinelander 2020-05-20 16:14:05 -03:00
parent 72bf215da4
commit bdc9c7bfa8
19 changed files with 223 additions and 190 deletions

View File

@ -60,7 +60,10 @@ add_library(lokinet-platform
ev/pipe.cpp ev/pipe.cpp
ev/vpnio.cpp ev/vpnio.cpp
ev/ev_libuv.cpp ev/ev_libuv.cpp
net/ip.cpp
net/ip_packet.cpp net/ip_packet.cpp
net/ip_range.cpp
net/net.cpp net/net.cpp
net/net_int.cpp net/net_int.cpp
$<TARGET_OBJECTS:tuntap> $<TARGET_OBJECTS:tuntap>

View File

@ -158,7 +158,7 @@ namespace llarp
} }
else else
{ {
const auto addr = net::IPPacket::TruncateV6(ip); const auto addr = net::TruncateV6(ip);
rec.rr_type = qTypeA; rec.rr_type = qTypeA;
rec.rData.resize(4); rec.rData.resize(4);
htobe32buf(rec.rData.data(), addr.h); htobe32buf(rec.rData.data(), addr.h);

View File

@ -98,7 +98,7 @@ namespace llarp
sub = sub.substr(pos + 1); sub = sub.substr(pos + 1);
pos = sub.find('.'); pos = sub.find('.');
a = atoi(sub.substr(0, pos).c_str()); a = atoi(sub.substr(0, pos).c_str());
ip = net::IPPacket::ExpandV4(llarp::ipaddr_ipv4_bits(a, b, c, d)); ip = net::ExpandV4(llarp::ipaddr_ipv4_bits(a, b, c, d));
return true; return true;
} }
if (numdots == 32 && isV6) if (numdots == 32 && isV6)

View File

@ -129,10 +129,10 @@ namespace llarp
{ {
huint32_t dst; huint32_t dst;
if (m_RewriteSource) if (m_RewriteSource)
dst = net::IPPacket::TruncateV6(m_Parent->GetIfAddr()); dst = net::TruncateV6(m_Parent->GetIfAddr());
else else
dst = pkt.dstv4(); dst = pkt.dstv4();
pkt.UpdateIPv4Address(xhtonl(net::IPPacket::TruncateV6(m_IP)), xhtonl(dst)); pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(m_IP)), xhtonl(dst));
} }
else else
{ {
@ -160,7 +160,7 @@ namespace llarp
pkt.UpdateIPv6Address(src, m_IP); pkt.UpdateIPv6Address(src, m_IP);
else else
pkt.UpdateIPv4Address( pkt.UpdateIPv4Address(
xhtonl(net::IPPacket::TruncateV6(src)), xhtonl(net::IPPacket::TruncateV6(m_IP))); xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(m_IP)));
const auto _pktbuf = pkt.Buffer(); const auto _pktbuf = pkt.Buffer();
const llarp_buffer_t& pktbuf = _pktbuf.underlying; const llarp_buffer_t& pktbuf = _pktbuf.underlying;

View File

@ -487,7 +487,7 @@ namespace llarp
pkt.UpdateIPv6Address(from, m_IfAddr); pkt.UpdateIPv6Address(from, m_IfAddr);
else else
pkt.UpdateIPv4Address( pkt.UpdateIPv4Address(
xhtonl(net::IPPacket::TruncateV6(from)), xhtonl(net::IPPacket::TruncateV6(m_IfAddr))); xhtonl(net::TruncateV6(from)), xhtonl(net::TruncateV6(m_IfAddr)));
return llarp_ev_tun_async_write(&m_Tun, pkt.Buffer()); return llarp_ev_tun_async_write(&m_Tun, pkt.Buffer());
} }

View File

@ -236,7 +236,7 @@ namespace llarp
huint128_t ipv6; huint128_t ipv6;
if (ip.FromString(ip_str)) if (ip.FromString(ip_str))
{ {
ipv6 = net::IPPacket::ExpandV4(ip); ipv6 = net::ExpandV4(ip);
} }
else if (ipv6.FromString(ip_str)) else if (ipv6.FromString(ip_str))
{ {
@ -767,7 +767,7 @@ namespace llarp
} }
if (ip.FromString(ifaddr)) if (ip.FromString(ifaddr))
{ {
m_OurIP = net::IPPacket::ExpandV4(ip); m_OurIP = net::ExpandV4(ip);
m_OurRange.netmask_bits = netmask_ipv6_bits(netmask + 96); m_OurRange.netmask_bits = netmask_ipv6_bits(netmask + 96);
} }
else if (m_OurIP.FromString(ifaddr)) else if (m_OurIP.FromString(ifaddr))
@ -866,7 +866,7 @@ namespace llarp
huint128_t dst; huint128_t dst;
if (pkt.IsV4()) if (pkt.IsV4())
dst = net::IPPacket::ExpandV4(pkt.dstv4()); dst = net::ExpandV4(pkt.dstv4());
else else
dst = pkt.dstv6(); dst = pkt.dstv6();
@ -951,7 +951,7 @@ namespace llarp
return false; return false;
} }
pkt.UpdateIPv4Address( pkt.UpdateIPv4Address(
xhtonl(net::IPPacket::TruncateV6(themIP)), xhtonl(net::IPPacket::TruncateV6(usIP))); xhtonl(net::TruncateV6(themIP)), xhtonl(net::TruncateV6(usIP)));
} }
else if (pkt.IsV6()) else if (pkt.IsV6())
{ {

View File

@ -4,6 +4,7 @@
#include <dns/server.hpp> #include <dns/server.hpp>
#include <ev/ev.h> #include <ev/ev.h>
#include <ev/vpnio.hpp> #include <ev/vpnio.hpp>
#include <net/ip.hpp>
#include <net/ip_packet.hpp> #include <net/ip_packet.hpp>
#include <net/net.hpp> #include <net/net.hpp>
#include <service/endpoint.hpp> #include <service/endpoint.hpp>
@ -242,7 +243,7 @@ namespace llarp
{ {
if (pkt.IsV4()) if (pkt.IsV4())
{ {
pkt.UpdateIPv6Address(net::IPPacket::ExpandV4(pkt.srcv4()), m_OurIP); pkt.UpdateIPv6Address(net::ExpandV4(pkt.srcv4()), m_OurIP);
} }
else else
{ {
@ -253,7 +254,7 @@ namespace llarp
{ {
if (pkt.IsV4()) if (pkt.IsV4())
pkt.UpdateIPv4Address( pkt.UpdateIPv4Address(
xhtonl(pkt.srcv4()), xhtonl(net::IPPacket::TruncateV6(m_OurIP))); xhtonl(pkt.srcv4()), xhtonl(net::TruncateV6(m_OurIP)));
else else
return false; return false;
} }

28
llarp/net/ip.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <net/ip.hpp>
#include <cstring>
namespace llarp::net {
huint128_t
In6ToHUInt(in6_addr addr)
{
uint8_t* ptr = reinterpret_cast<uint8_t*>(addr.s6_addr);
uint128_t x{0};
for (int i = 0; i < 16; i++)
{
x <<= 8;
x |= ptr[i];
}
return huint128_t{x};
}
in6_addr
HUIntToIn6(huint128_t x)
{
in6_addr addr;
auto i = ntoh128(x.h);
std::memcpy(&addr, &i, 16);
return addr;
}
} // namespace llarp::net

28
llarp/net/ip.hpp Normal file
View File

@ -0,0 +1,28 @@
#pragma once
#include <net/net_int.hpp>
#include <net/net.hpp>
#include <cstdint>
namespace llarp::net
{
huint128_t
In6ToHUInt(in6_addr addr);
in6_addr
HUIntToIn6(huint128_t x);
constexpr huint128_t
ExpandV4(huint32_t x)
{
return huint128_t{0xffff'0000'0000UL} | huint128_t{x.h};
}
constexpr huint32_t
TruncateV6(huint128_t x)
{
huint32_t ret = {0};
ret.h = (uint32_t)(x.h & 0x0000'0000'ffff'ffffUL);
return ret;
}
} // namespace llarp::net

View File

@ -1,4 +1,5 @@
#include <net/ip_packet.hpp> #include <net/ip_packet.hpp>
#include <net/ip.hpp>
#include <util/buffer.hpp> #include <util/buffer.hpp>
#include <util/endian.hpp> #include <util/endian.hpp>
@ -27,44 +28,6 @@ namespace llarp
return (uint32_t*)addr.s6_addr; return (uint32_t*)addr.s6_addr;
} }
huint128_t
IPPacket::In6ToHUInt(in6_addr addr)
{
uint8_t* ptr = reinterpret_cast<uint8_t*>(addr.s6_addr);
uint128_t x{0};
for (int i = 0; i < 16; i++)
{
x <<= 8;
x |= ptr[i];
}
return huint128_t{x};
}
in6_addr
IPPacket::HUIntToIn6(huint128_t x)
{
in6_addr addr;
auto i = ntoh128(x.h);
memcpy(&addr, &i, 16);
return addr;
}
huint128_t
IPPacket::ExpandV4(huint32_t i)
{
huint128_t ff = {0xff};
huint128_t expanded{i.h};
return (ff << 40) | (ff << 32) | expanded;
}
huint32_t
IPPacket::TruncateV6(huint128_t i)
{
huint32_t ret = {0};
ret.h = (uint32_t)(i.h & (0x00000000ffffffffUL));
return ret;
}
huint128_t huint128_t
IPPacket::srcv6() const IPPacket::srcv6() const
{ {

View File

@ -98,18 +98,6 @@ namespace llarp
/// an Packet /// an Packet
struct IPPacket struct IPPacket
{ {
static huint128_t
In6ToHUInt(in6_addr addr);
static in6_addr
HUIntToIn6(huint128_t x);
static huint128_t
ExpandV4(huint32_t x);
static huint32_t
TruncateV6(huint128_t x);
static constexpr size_t MaxSize = 1500; static constexpr size_t MaxSize = 1500;
llarp_time_t timestamp; llarp_time_t timestamp;
size_t sz; size_t sz;

76
llarp/net/ip_range.cpp Normal file
View File

@ -0,0 +1,76 @@
#include <net/ip_range.hpp>
namespace llarp
{
bool
IPRange::ContainsV4(const huint32_t& ip) const
{
return Contains(net::ExpandV4(ip));
}
bool
IPRange::FromString(std::string str)
{
const auto colinpos = str.find(":");
const auto slashpos = str.find("/");
std::string bitsstr;
if (slashpos != std::string::npos)
{
bitsstr = str.substr(slashpos + 1);
str = str.substr(0, slashpos);
}
if (colinpos == std::string::npos)
{
huint32_t ip;
if (!ip.FromString(str))
return false;
addr = net::ExpandV4(ip);
if (!bitsstr.empty())
{
auto bits = atoi(bitsstr.c_str());
if (bits < 0 || bits > 32)
return false;
netmask_bits = netmask_ipv6_bits(96 + bits);
}
else
netmask_bits = netmask_ipv6_bits(128);
}
else
{
if (!addr.FromString(str))
return false;
if (!bitsstr.empty())
{
auto bits = atoi(bitsstr.c_str());
if (bits < 0 || bits > 128)
return false;
netmask_bits = netmask_ipv6_bits(bits);
}
else
{
netmask_bits = netmask_ipv6_bits(128);
}
}
return true;
}
std::string
IPRange::ToString() const
{
char buf[INET6_ADDRSTRLEN + 1] = {0};
std::string str;
in6_addr inaddr = {};
size_t numset = 0;
uint128_t bits = netmask_bits.h;
while (bits)
{
if (bits & 1)
numset++;
bits >>= 1;
}
str += inet_ntop(AF_INET6, &inaddr, buf, sizeof(buf));
return str + "/" + std::to_string(numset);
}
} // namespace llarp

61
llarp/net/ip_range.hpp Normal file
View File

@ -0,0 +1,61 @@
#pragma once
#include <ostream>
#include <net/ip.hpp>
#include <util/bits.hpp>
#include <util/types.hpp>
#include <string>
namespace llarp
{
struct IPRange
{
using Addr_t = huint128_t;
huint128_t addr = {0};
huint128_t netmask_bits = {0};
static constexpr IPRange
FromIPv4(byte_t a, byte_t b, byte_t c, byte_t d, byte_t mask)
{
return IPRange{net::ExpandV4(ipaddr_ipv4_bits(a, b, c, d)),
netmask_ipv6_bits(mask + 96)};
}
/// return true if ip is contained in this ip range
constexpr bool
Contains(const Addr_t& ip) const
{
return (addr & netmask_bits) == (ip & netmask_bits);
}
bool
ContainsV4(const huint32_t& ip) const;
friend std::ostream&
operator<<(std::ostream& out, const IPRange& a)
{
return out << a.ToString();
}
/// get the highest address on this range
huint128_t
HighestAddr() const
{
return (addr & netmask_bits) + (huint128_t{1} << (128 - bits::count_bits_128(netmask_bits.h)))
- huint128_t{1};
}
bool
operator<(const IPRange& other) const
{
return (this->addr & this->netmask_bits) < (other.addr & other.netmask_bits)
|| this->netmask_bits < other.netmask_bits;
}
std::string
ToString() const;
bool
FromString(std::string str);
};
} // namespace llarp

View File

@ -1,7 +1,7 @@
#ifndef LLARP_NET_IP_RANGE_MAP_HPP #ifndef LLARP_NET_IP_RANGE_MAP_HPP
#define LLARP_NET_IP_RANGE_MAP_HPP #define LLARP_NET_IP_RANGE_MAP_HPP
#include <net/ip.hpp> #include <net/ip_range.hpp>
namespace llarp namespace llarp
{ {

View File

@ -15,6 +15,7 @@
#endif #endif
#include <net/ip.hpp> #include <net/ip.hpp>
#include <net/ip_range.hpp>
#include <util/logging/logger.hpp> #include <util/logging/logger.hpp>
#include <util/str.hpp> #include <util/str.hpp>
@ -464,8 +465,8 @@ namespace llarp
if (addr->sin_addr.s_addr) if (addr->sin_addr.s_addr)
// skip unconfig'd adapters (windows passes these through the unix-y // skip unconfig'd adapters (windows passes these through the unix-y
// wrapper) // wrapper)
currentRanges.emplace_back(IPRange{net::IPPacket::ExpandV4(xntohl(ifaddr)), currentRanges.emplace_back(IPRange{net::ExpandV4(xntohl(ifaddr)),
net::IPPacket::ExpandV4(xntohl(ifmask))}); net::ExpandV4(xntohl(ifmask))});
} }
}); });
// try 10.x.0.0/16 // try 10.x.0.0/16
@ -602,76 +603,6 @@ namespace llarp
return IsBogon(host); return IsBogon(host);
} }
bool
IPRange::ContainsV4(const huint32_t& ip) const
{
return Contains(net::IPPacket::ExpandV4(ip));
}
bool
IPRange::FromString(std::string str)
{
const auto colinpos = str.find(":");
const auto slashpos = str.find("/");
std::string bitsstr;
if (slashpos != std::string::npos)
{
bitsstr = str.substr(slashpos + 1);
str = str.substr(0, slashpos);
}
if (colinpos == std::string::npos)
{
huint32_t ip;
if (!ip.FromString(str))
return false;
addr = net::IPPacket::ExpandV4(ip);
if (!bitsstr.empty())
{
auto bits = atoi(bitsstr.c_str());
if (bits < 0 || bits > 32)
return false;
netmask_bits = netmask_ipv6_bits(96 + bits);
}
else
netmask_bits = netmask_ipv6_bits(128);
}
else
{
if (!addr.FromString(str))
return false;
if (!bitsstr.empty())
{
auto bits = atoi(bitsstr.c_str());
if (bits < 0 || bits > 128)
return false;
netmask_bits = netmask_ipv6_bits(bits);
}
else
{
netmask_bits = netmask_ipv6_bits(128);
}
}
return true;
}
std::string
IPRange::ToString() const
{
char buf[INET6_ADDRSTRLEN + 1] = {0};
std::string str;
in6_addr inaddr = {};
size_t numset = 0;
uint128_t bits = netmask_bits.h;
while (bits)
{
if (bits & 1)
numset++;
bits >>= 1;
}
str += inet_ntop(AF_INET6, &inaddr, buf, sizeof(buf));
return str + "/" + std::to_string(numset);
}
IPRange IPRange
iprange_ipv4(byte_t a, byte_t b, byte_t c, byte_t d, byte_t mask) iprange_ipv4(byte_t a, byte_t b, byte_t c, byte_t d, byte_t mask)
{ {

View File

@ -57,52 +57,6 @@ llarp_getPrivateIfs();
namespace llarp namespace llarp
{ {
struct IPRange
{
using Addr_t = huint128_t;
huint128_t addr = {0};
huint128_t netmask_bits = {0};
/// return true if ip is contained in this ip range
bool
Contains(const Addr_t& ip) const
{
return (addr & netmask_bits) == (ip & netmask_bits);
}
bool
ContainsV4(const huint32_t& ip) const;
friend std::ostream&
operator<<(std::ostream& out, const IPRange& a)
{
return out << a.ToString();
}
/// get the highest address on this range
huint128_t
HighestAddr() const
{
return (addr & netmask_bits) + (huint128_t{1} << (128 - bits::count_bits_128(netmask_bits.h)))
- huint128_t{1};
}
bool
operator<(const IPRange& other) const
{
return (this->addr & this->netmask_bits) < (other.addr & other.netmask_bits)
|| this->netmask_bits < other.netmask_bits;
}
std::string
ToString() const;
bool
FromString(std::string str);
};
huint128_t
ExpandV4(huint32_t x);
/// get a netmask with the higest numset bits set /// get a netmask with the higest numset bits set
constexpr huint128_t constexpr huint128_t

View File

@ -20,7 +20,7 @@ namespace llarp
huint128_t::ToV6(V6Container& c) huint128_t::ToV6(V6Container& c)
{ {
c.resize(16); c.resize(16);
const in6_addr addr = net::IPPacket::HUIntToIn6(*this); const in6_addr addr = net::HUIntToIn6(*this);
std::copy_n(addr.s6_addr, 16, c.begin()); std::copy_n(addr.s6_addr, 16, c.begin());
} }

View File

@ -52,7 +52,7 @@ TEST_F(DNSLibTest, TestPTR)
{ {
llarp::huint128_t ip = {0}; llarp::huint128_t ip = {0};
llarp::huint128_t expected = llarp::huint128_t expected =
llarp::net::IPPacket::ExpandV4(llarp::ipaddr_ipv4_bits(10, 10, 10, 1)); llarp::net::ExpandV4(llarp::ipaddr_ipv4_bits(10, 10, 10, 1));
ASSERT_TRUE(llarp::dns::DecodePTR("1.10.10.10.in-addr.arpa.", ip)); ASSERT_TRUE(llarp::dns::DecodePTR("1.10.10.10.in-addr.arpa.", ip));
ASSERT_EQ(ip, expected); ASSERT_EQ(ip, expected);
} }

View File

@ -1,8 +1,8 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <net/net.hpp>
#include <net/net_int.hpp> #include <net/net_int.hpp>
#include <net/ip.hpp> #include <net/ip.hpp>
#include <net/ip_range.hpp>
struct TestNet : public ::testing::Test struct TestNet : public ::testing::Test
{ {
@ -26,7 +26,7 @@ TEST_F(TestNet, TestIn6AddrToHUIntLoopback)
llarp::huint128_t loopback = {0}; llarp::huint128_t loopback = {0};
ASSERT_TRUE(loopback.FromString("::1")); ASSERT_TRUE(loopback.FromString("::1"));
in6_addr addr = IN6ADDR_LOOPBACK_INIT; in6_addr addr = IN6ADDR_LOOPBACK_INIT;
auto huint = llarp::net::IPPacket::In6ToHUInt(addr); auto huint = llarp::net::In6ToHUInt(addr);
ASSERT_EQ(huint, loopback); ASSERT_EQ(huint, loopback);
} }
@ -35,7 +35,7 @@ TEST_F(TestNet, TestIn6AddrToHUInt)
llarp::huint128_t huint_parsed = {0}; llarp::huint128_t huint_parsed = {0};
ASSERT_TRUE(huint_parsed.FromString("fd00::1")); ASSERT_TRUE(huint_parsed.FromString("fd00::1"));
in6_addr addr = { { { 0xfd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; in6_addr addr = { { { 0xfd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
auto huint = llarp::net::IPPacket::In6ToHUInt(addr); auto huint = llarp::net::In6ToHUInt(addr);
ASSERT_EQ(huint, huint_parsed); ASSERT_EQ(huint, huint_parsed);
huint_parsed.h ++; huint_parsed.h ++;
ASSERT_NE(huint, huint_parsed); ASSERT_NE(huint, huint_parsed);
@ -44,19 +44,19 @@ TEST_F(TestNet, TestIn6AddrToHUInt)
TEST_F(TestNet, TestRangeContains8) TEST_F(TestNet, TestRangeContains8)
{ {
ASSERT_TRUE(llarp::iprange_ipv4(10, 0, 0, 1, 8) ASSERT_TRUE(llarp::IPRange::FromIPv4(10, 0, 0, 1, 8)
.ContainsV4(llarp::ipaddr_ipv4_bits(10, 40, 11, 6))); .ContainsV4(llarp::ipaddr_ipv4_bits(10, 40, 11, 6)));
} }
TEST_F(TestNet, TestRangeContains24) TEST_F(TestNet, TestRangeContains24)
{ {
ASSERT_TRUE(llarp::iprange_ipv4(10, 200, 0, 1, 24) ASSERT_TRUE(llarp::IPRange::FromIPv4(10, 200, 0, 1, 24)
.ContainsV4(llarp::ipaddr_ipv4_bits(10, 200, 0, 253))); .ContainsV4(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
} }
TEST_F(TestNet, TestRangeContainsFail) TEST_F(TestNet, TestRangeContainsFail)
{ {
ASSERT_TRUE(!llarp::iprange_ipv4(192, 168, 0, 1, 24) ASSERT_TRUE(!llarp::IPRange::FromIPv4(192, 168, 0, 1, 24)
.ContainsV4(llarp::ipaddr_ipv4_bits(10, 200, 0, 253))); .ContainsV4(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
} }