pull/686/head
Jeff Becker 5 years ago
parent 32d73199e6
commit 2403ab8f86
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -65,9 +65,11 @@ set(LIB_PLATFORM_SRC
ev/pipe.cpp
metrics/metrictank_publisher.cpp
metrics/publishers.cpp
net/ip.cpp
net/net.cpp
net/net_addr.cpp
net/net_inaddr.cpp
net/net_int.cpp
# for android shim
${ANDROID_PLATFORM_SRC}
# process isolation implementation
@ -194,8 +196,6 @@ set(LIB_SRC
messages/transfer_traffic.cpp
net/address_info.cpp
net/exit_info.cpp
net/ip.cpp
net/net_int.cpp
nodedb.cpp
path/path.cpp
path/path_types.cpp

@ -5,6 +5,7 @@
#include <util/endian.hpp>
#include <util/logger.hpp>
#include <util/printer.hpp>
#include <net/ip.hpp>
#include <array>
@ -165,7 +166,7 @@ namespace llarp
}
void
Message::AddINReply(llarp::huint32_t ip, bool isV6, RR_TTL_t ttl)
Message::AddINReply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl)
{
if(questions.size())
{
@ -182,9 +183,10 @@ namespace llarp
}
else
{
rec.rr_type = qTypeA;
const auto addr = net::IPPacket::TruncateV6(ip);
rec.rr_type = qTypeA;
rec.rData.resize(4);
htobe32buf(rec.rData.data(), ip.h);
htobe32buf(rec.rData.data(), addr.h);
}
answers.emplace_back(std::move(rec));
}

@ -64,7 +64,7 @@ namespace llarp
AddCNAMEReply(std::string name, RR_TTL_t ttl = 1);
void
AddINReply(llarp::huint32_t addr, bool isV6, RR_TTL_t ttl = 1);
AddINReply(llarp::huint128_t addr, bool isV6, RR_TTL_t ttl = 1);
void
AddAReply(std::string name, RR_TTL_t ttl = 1);

@ -154,9 +154,9 @@ llarp_ev_add_tun(struct llarp_ev_loop *loop, struct llarp_tun_io *tun)
dev->setup();
return dev->add_ev(); // start up tun and add to event queue
}
#endif
llarp::LogWarn("Loop could not create tun");
return false;
#endif
}
bool

@ -613,6 +613,7 @@ namespace libuv
m_CloseFuncs.emplace_back(std::bind(&tun_glue ::Close, glue));
return true;
}
delete glue;
return false;
}

@ -8,7 +8,7 @@ namespace llarp
{
Endpoint::Endpoint(const llarp::PubKey& remoteIdent,
const llarp::PathID_t& beginPath, bool rewriteIP,
huint32_t ip, llarp::handlers::ExitEndpoint* parent)
huint128_t ip, llarp::handlers::ExitEndpoint* parent)
: createdAt(parent->Now())
, m_Parent(parent)
, m_remoteSignKey(remoteIdent)
@ -108,16 +108,16 @@ namespace llarp
if(m_UpstreamQueue.size() > MaxUpstreamQueueSize)
return false;
llarp::net::IPv4Packet pkt;
llarp::net::IPPacket pkt;
if(!pkt.Load(buf.underlying))
return false;
huint32_t dst;
if(m_RewriteSource)
dst = m_Parent->GetIfAddr();
dst = net::IPPacket::TruncateV6(m_Parent->GetIfAddr());
else
dst = pkt.dst();
pkt.UpdateIPv4PacketOnDst(m_IP, dst);
dst = pkt.dstv4();
pkt.UpdateV4Address(net::IPPacket::TruncateV6(m_IP), dst);
m_UpstreamQueue.emplace(pkt, counter);
m_TxRate += buf.underlying.sz;
m_LastActive = m_Parent->Now();
@ -127,16 +127,16 @@ namespace llarp
bool
Endpoint::QueueInboundTraffic(ManagedBuffer buf)
{
llarp::net::IPv4Packet pkt;
llarp::net::IPPacket pkt;
if(!pkt.Load(buf.underlying))
return false;
huint32_t src;
huint128_t src;
if(m_RewriteSource)
src = m_Parent->GetIfAddr();
else
src = pkt.src();
pkt.UpdateIPv4PacketOnDst(src, m_IP);
src = pkt.srcv6();
pkt.UpdateV6Address(src, m_IP);
const llarp_buffer_t& pktbuf = pkt.Buffer(); // life time extension
const uint8_t queue_idx = pktbuf.sz / llarp::routing::ExitPadSize;
if(m_DownstreamQueues.find(queue_idx) == m_DownstreamQueues.end())

@ -24,7 +24,7 @@ namespace llarp
static constexpr size_t MaxUpstreamQueueSize = 256;
Endpoint(const llarp::PubKey& remoteIdent,
const llarp::PathID_t& beginPath, bool rewriteIP, huint32_t ip,
const llarp::PathID_t& beginPath, bool rewriteIP, huint128_t ip,
llarp::handlers::ExitEndpoint* parent);
~Endpoint();
@ -97,7 +97,7 @@ namespace llarp
return m_RxRate;
}
huint32_t
huint128_t
LocalIP() const
{
return m_IP;
@ -109,7 +109,7 @@ namespace llarp
llarp::handlers::ExitEndpoint* m_Parent;
llarp::PubKey m_remoteSignKey;
llarp::PathID_t m_CurrentPath;
llarp::huint32_t m_IP;
llarp::huint128_t m_IP;
uint64_t m_TxRate, m_RxRate;
llarp_time_t m_LastActive;
bool m_RewriteSource;
@ -121,12 +121,12 @@ namespace llarp
struct UpstreamBuffer
{
UpstreamBuffer(const llarp::net::IPv4Packet& p, uint64_t c)
UpstreamBuffer(const llarp::net::IPPacket& p, uint64_t c)
: pkt(p), counter(c)
{
}
llarp::net::IPv4Packet pkt;
llarp::net::IPPacket pkt;
uint64_t counter;
bool

@ -199,7 +199,7 @@ namespace llarp
{
if(m_WritePacket)
{
llarp::net::IPv4Packet pkt;
llarp::net::IPPacket pkt;
if(!pkt.Load(buf))
return false;
m_Downstream.emplace(counter, pkt);
@ -221,8 +221,7 @@ namespace llarp
}
bool
BaseSession::QueueUpstreamTraffic(llarp::net::IPv4Packet pkt,
const size_t N)
BaseSession::QueueUpstreamTraffic(llarp::net::IPPacket pkt, const size_t N)
{
const llarp_buffer_t& buf = pkt.Buffer();
auto& queue = m_Upstream[buf.sz / N];

@ -74,7 +74,7 @@ namespace llarp
HandlePathBuilt(llarp::path::Path_ptr p) override;
bool
QueueUpstreamTraffic(llarp::net::IPv4Packet pkt, const size_t packSize);
QueueUpstreamTraffic(llarp::net::IPPacket pkt, const size_t packSize);
/// flush upstream to exit via paths
bool
@ -139,7 +139,7 @@ namespace llarp
using TieredQueue_t = std::map< uint8_t, UpstreamTrafficQueue_t >;
TieredQueue_t m_Upstream;
using DownstreamPkt = std::pair< uint64_t, llarp::net::IPv4Packet >;
using DownstreamPkt = std::pair< uint64_t, llarp::net::IPPacket >;
struct DownstreamPktSorter
{

@ -68,7 +68,7 @@ namespace llarp
huint32_t ip;
if(!dns::DecodePTR(msg.questions[0].qname, ip))
return false;
return m_OurRange.Contains(ip);
return m_OurRange.ContainsV4(ip);
}
else if(msg.questions[0].qtype == dns::qTypeA
|| msg.questions[0].qtype == dns::qTypeCNAME
@ -91,14 +91,15 @@ namespace llarp
huint32_t ip;
if(!dns::DecodePTR(msg.questions[0].qname, ip))
return false;
if(ip == m_IfAddr)
huint128_t ipv6 = net::IPPacket::ExpandV4(ip);
if(ipv6 == m_IfAddr)
{
RouterID us = GetRouter()->pubkey();
msg.AddAReply(us.ToString(), 300);
}
else
{
auto itr = m_IPToKey.find(ip);
auto itr = m_IPToKey.find(ipv6);
if(itr != m_IPToKey.end()
&& m_SNodeKeys.find(itr->second) != m_SNodeKeys.end())
{
@ -155,7 +156,7 @@ namespace llarp
RouterID r;
if(r.FromString(msg.questions[0].Name()))
{
huint32_t ip;
huint128_t ip;
PubKey pubKey(r);
if(m_SNodeKeys.find(pubKey) == m_SNodeKeys.end())
{
@ -212,11 +213,12 @@ namespace llarp
m_InetToNetwork.Process([&](Pkt_t &pkt) {
PubKey pk;
{
auto itr = m_IPToKey.find(pkt.dst());
auto itr = m_IPToKey.find(pkt.dstv6());
if(itr == m_IPToKey.end())
{
// drop
LogWarn(Name(), " dropping packet, has no session at ", pkt.dst());
LogWarn(Name(), " dropping packet, has no session at ",
pkt.dstv4());
return;
}
pk = itr->second;
@ -285,10 +287,10 @@ namespace llarp
{
// map our address
const PubKey us(m_Router->pubkey());
const huint32_t ip = GetIfAddr();
m_KeyToIP[us] = ip;
m_IPToKey[ip] = us;
m_IPActivity[ip] = std::numeric_limits< llarp_time_t >::max();
const huint128_t ip = GetIfAddr();
m_KeyToIP[us] = ip;
m_IPToKey[ip] = us;
m_IPActivity[ip] = std::numeric_limits< llarp_time_t >::max();
m_SNodeKeys.insert(us);
if(m_ShouldInitTun)
{
@ -311,7 +313,7 @@ namespace llarp
return m_Router;
}
huint32_t
huint128_t
ExitEndpoint::GetIfAddr() const
{
return m_IfAddr;
@ -340,10 +342,10 @@ namespace llarp
return m_KeyToIP.find(pk) != m_KeyToIP.end();
}
huint32_t
huint128_t
ExitEndpoint::GetIPForIdent(const PubKey pk)
{
huint32_t found = {0};
huint128_t found = {0};
if(!HasLocalMappedAddrFor(pk))
{
// allocate and map
@ -372,14 +374,14 @@ namespace llarp
return found;
}
huint32_t
huint128_t
ExitEndpoint::AllocateNewAddress()
{
if(m_NextAddr < m_HigestAddr)
return ++m_NextAddr;
// find oldest activity ip address
huint32_t found = {0};
huint128_t found = {0};
llarp_time_t min = std::numeric_limits< llarp_time_t >::max();
auto itr = m_IPActivity.begin();
while(itr != m_IPActivity.end())
@ -409,7 +411,7 @@ namespace llarp
ExitEndpoint::KickIdentOffExit(const PubKey &pk)
{
LogInfo(Name(), " kicking ", pk, " off exit");
huint32_t ip = m_KeyToIP[pk];
huint128_t ip = m_KeyToIP[pk];
m_KeyToIP.erase(pk);
m_IPToKey.erase(ip);
auto range = m_ActiveExits.equal_range(pk);
@ -419,7 +421,7 @@ namespace llarp
}
void
ExitEndpoint::MarkIPActive(huint32_t ip)
ExitEndpoint::MarkIPActive(huint128_t ip)
{
m_IPActivity[ip] = GetRouter()->Now();
}
@ -432,13 +434,13 @@ namespace llarp
}
bool
ExitEndpoint::QueueSNodePacket(const llarp_buffer_t &buf, huint32_t from)
ExitEndpoint::QueueSNodePacket(const llarp_buffer_t &buf, huint128_t from)
{
net::IPv4Packet pkt;
net::IPPacket pkt;
if(!pkt.Load(buf))
return false;
// rewrite ip
pkt.UpdateIPv4PacketOnDst(from, m_IfAddr);
pkt.UpdateV6Address(from, m_IfAddr);
return llarp_ev_tun_async_write(&m_Tun, pkt.Buffer());
}
@ -529,12 +531,19 @@ namespace llarp
strncpy(m_Tun.ifaddr, host_str.c_str(), sizeof(m_Tun.ifaddr) - 1);
m_Tun.netmask = std::atoi(nmask_str.c_str());
Addr ifaddr(host_str);
m_IfAddr = ifaddr.xtohl();
m_OurRange.netmask_bits = netmask_ipv4_bits(m_Tun.netmask);
m_OurRange.addr = m_IfAddr;
m_NextAddr = m_IfAddr;
m_HigestAddr = m_IfAddr | (~m_OurRange.netmask_bits);
huint32_t ip;
if(ip.FromString(host_str))
{
m_IfAddr = net::IPPacket::ExpandV4(ip);
m_OurRange.netmask_bits = netmask_ipv6_bits(m_Tun.netmask + 96);
}
else if(m_IfAddr.FromString(host_str))
{
m_OurRange.netmask_bits = netmask_ipv6_bits(m_Tun.netmask);
}
m_OurRange.addr = m_IfAddr;
m_NextAddr = m_IfAddr;
m_HigestAddr = m_IfAddr | (~m_OurRange.netmask_bits);
LogInfo(Name(), " set ifaddr range to ", m_Tun.ifaddr, "/",
m_Tun.netmask, " lo=", m_IfAddr, " hi=", m_HigestAddr);
}
@ -564,7 +573,7 @@ namespace llarp
return true;
}
huint32_t
huint128_t
ExitEndpoint::ObtainServiceNodeIP(const RouterID &other)
{
const PubKey pubKey(other);
@ -573,7 +582,7 @@ namespace llarp
if(pubKey == us)
return m_IfAddr;
huint32_t ip = GetIPForIdent(pubKey);
huint128_t ip = GetIPForIdent(pubKey);
if(m_SNodeKeys.emplace(pubKey).second)
{
auto session = std::make_shared< exit::SNodeSession >(
@ -593,7 +602,7 @@ namespace llarp
{
if(wantInternet && !m_PermitExit)
return false;
huint32_t ip = GetIPForIdent(pk);
auto ip = GetIPForIdent(pk);
if(GetRouter()->pathContext().TransitHopPreviousIsRouter(path,
pk.as_array()))
{

@ -99,29 +99,29 @@ namespace llarp
bool
HasLocalMappedAddrFor(const PubKey& pk) const;
huint32_t
huint128_t
GetIfAddr() const;
void
Flush();
private:
huint32_t
huint128_t
GetIPForIdent(const PubKey pk);
huint32_t
huint128_t
AllocateNewAddress();
/// obtain ip for service node session, creates a new session if one does
/// not existing already
huint32_t
huint128_t
ObtainServiceNodeIP(const RouterID& router);
bool
QueueSNodePacket(const llarp_buffer_t& buf, huint32_t from);
QueueSNodePacket(const llarp_buffer_t& buf, huint128_t from);
void
MarkIPActive(huint32_t ip);
MarkIPActive(huint128_t ip);
void
KickIdentOffExit(const PubKey& pk);
@ -139,7 +139,7 @@ namespace llarp
PubKey::Hash >
m_ActiveExits;
using KeyMap_t = std::unordered_map< PubKey, huint32_t, PubKey::Hash >;
using KeyMap_t = std::unordered_map< PubKey, huint128_t, PubKey::Hash >;
KeyMap_t m_KeyToIP;
@ -153,14 +153,15 @@ namespace llarp
/// snode sessions we are talking to directly
SNodeSessions_t m_SNodeSessions;
std::unordered_map< huint32_t, PubKey, huint32_t::Hash > m_IPToKey;
std::unordered_map< huint128_t, PubKey, huint128_t::Hash > m_IPToKey;
huint32_t m_IfAddr;
huint32_t m_HigestAddr;
huint32_t m_NextAddr;
huint128_t m_IfAddr;
huint128_t m_HigestAddr;
huint128_t m_NextAddr;
IPRange m_OurRange;
std::unordered_map< huint32_t, llarp_time_t, huint32_t::Hash >
std::unordered_map< huint128_t, llarp_time_t, huint128_t::Hash >
m_IPActivity;
llarp_tun_io m_Tun;
@ -168,7 +169,7 @@ namespace llarp
Addr m_LocalResolverAddr;
std::vector< Addr > m_UpstreamResolvers;
using Pkt_t = net::IPv4Packet;
using Pkt_t = net::IPPacket;
using PacketQueue_t =
util::CoDelQueue< Pkt_t, Pkt_t::GetTime, Pkt_t::PutTime,
Pkt_t::CompareOrder, Pkt_t::GetNow, util::NullMutex,

@ -19,7 +19,7 @@ namespace llarp
bool
HandleWriteIPPacket(const llarp_buffer_t &,
std::function< huint32_t(void) >) override
std::function< huint128_t(void) >) override
{
return true;
}
@ -30,7 +30,13 @@ namespace llarp
return shared_from_this();
}
huint32_t
bool
SupportsV6() const override
{
return false;
}
huint128_t
ObtainIPForAddr(const AlignedBuffer< 32 > &, bool) override
{
return {0};

@ -200,13 +200,22 @@ namespace llarp
return false;
}
auto ip_str = v.substr(pos + 1);
in_addr ip;
if(inet_pton(AF_INET, ip_str.c_str(), &ip) != 1)
huint32_t ip;
huint128_t ipv6;
if(ip.FromString(ip_str))
{
llarp::LogError("cannot map to invalid ip ", ip_str);
ipv6 = net::IPPacket::ExpandV4(ip);
}
else if(ipv6.FromString(ip_str))
{
}
else
{
llarp::LogError(Name(), "failed to map ", ip_str,
" failed to parse IP");
return false;
}
return MapAddress(addr, huint32_t{ntohl(ip.s_addr)}, false);
return MapAddress(addr, ipv6, false);
}
if(k == "ifname")
{
@ -222,6 +231,7 @@ namespace llarp
if(k == "ifaddr")
{
std::string addr;
m_UseV6 = addr.find(":") != std::string::npos;
auto pos = v.find("/");
if(pos != std::string::npos)
{
@ -245,8 +255,11 @@ namespace llarp
}
else
{
tunif.netmask = 32;
addr = v;
if(m_UseV6)
tunif.netmask = 128;
else
tunif.netmask = 32;
addr = v;
}
llarp::LogInfo(Name() + " set ifaddr to ", addr, " with netmask ",
tunif.netmask);
@ -257,17 +270,16 @@ namespace llarp
}
bool
TunEndpoint::HasLocalIP(const huint32_t &ip) const
TunEndpoint::HasLocalIP(const huint128_t &ip) const
{
return m_IPToAddr.find(ip) != m_IPToAddr.end();
}
bool
TunEndpoint::QueueOutboundTraffic(llarp::net::IPv4Packet &&pkt)
TunEndpoint::QueueOutboundTraffic(llarp::net::IPPacket &&pkt)
{
return m_NetworkToUserPktQueue.EmplaceIf(
[](llarp::net::IPv4Packet &) -> bool { return true; },
std::move(pkt));
[](llarp::net::IPPacket &) -> bool { return true; }, std::move(pkt));
}
void
@ -354,7 +366,8 @@ namespace llarp
else if(msg.questions[0].qtype == dns::qTypeA
|| msg.questions[0].qtype == dns::qTypeAAAA)
{
const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA;
const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA && SupportsV6();
const bool isV4 = msg.questions[0].qtype == dns::qTypeA;
llarp::service::Address addr;
// on MacOS this is a typeA query
if(is_random_snode(msg))
@ -371,7 +384,7 @@ namespace llarp
context->ForEachService(
[&](const std::string &,
const std::shared_ptr< service::Endpoint > &service) -> bool {
huint32_t ip = service->GetIfAddr();
huint128_t ip = service->GetIfAddr();
if(ip.h)
{
msg.AddINReply(ip, isV6);
@ -384,10 +397,14 @@ namespace llarp
}
else if(addr.FromString(qname, ".loki"))
{
if(HasAddress(addr))
if(isV4 && SupportsV6())
{
huint32_t ip = ObtainIPForAddr(addr, false);
msg.AddINReply(ip, isV6);
msg.AddNXReply();
}
else if(HasAddress(addr))
{
huint128_t ip = ObtainIPForAddr(addr, false);
msg.AddINReply(ip, isV6);
}
else
{
@ -397,7 +414,7 @@ namespace llarp
return EnsurePathToService(
addr,
[=](const Address &, OutboundContext *ctx) {
SendDNSReply(addr, ctx, replyMsg, reply, false, isV6);
SendDNSReply(addr, ctx, replyMsg, reply, false, isV6 || !isV4);
},
2000);
}
@ -419,22 +436,24 @@ namespace llarp
else if(msg.questions[0].qtype == dns::qTypePTR)
{
// reverse dns
huint32_t ip = {0};
huint128_t ipv6 = {0};
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
{
msg.AddNXReply();
reply(msg);
return true;
}
ipv6 = net::IPPacket::ExpandV4(ip);
llarp::service::Address addr(
ObtainAddrForIP< llarp::service::Address >(ip, true));
ObtainAddrForIP< llarp::service::Address >(ipv6, true));
if(!addr.IsZero())
{
msg.AddAReply(addr.ToString(".snode"));
reply(msg);
return true;
}
addr = ObtainAddrForIP< llarp::service::Address >(ip, false);
addr = ObtainAddrForIP< llarp::service::Address >(ipv6, false);
if(!addr.IsZero())
{
msg.AddAReply(addr.ToString(".loki"));
@ -461,6 +480,12 @@ namespace llarp
m_Exit->ResetInternalState();
}
bool
TunEndpoint::SupportsV6() const
{
return m_UseV6;
}
// FIXME: pass in which question it should be addressing
bool
TunEndpoint::ShouldHookDNSMessage(const dns::Message &msg) const
@ -480,20 +505,19 @@ namespace llarp
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
return false;
return m_OurRange.Contains(ip);
return m_OurRange.ContainsV4(ip);
}
}
return false;
}
bool
TunEndpoint::MapAddress(const service::Address &addr, huint32_t ip,
TunEndpoint::MapAddress(const service::Address &addr, huint128_t ip,
bool SNode)
{
auto itr = m_IPToAddr.find(ip);
if(itr != m_IPToAddr.end())
{
// XXX is calling inet_ntoa safe in this context? it's MP-unsafe
llarp::LogWarn(ip, " already mapped to ",
service::Address(itr->second.as_array()).ToString());
return false;
@ -572,31 +596,44 @@ namespace llarp
*/
if(res->ai_family == AF_INET6)
{
llarp::LogError(Name(),
" failed to set up tun interface, we don't support "
"IPv6 format");
return false;
m_UseV6 = true;
}
freeaddrinfo(res);
struct in_addr addr; // network byte order
if(inet_aton(tunif.ifaddr, &addr) == 0)
freeaddrinfo(res);
if(m_UseV6)
{
llarp::LogError(Name(), " failed to set up tun interface, cant parse ",
tunif.ifaddr);
return false;
llarp::LogInfo(Name(), " using IPV6");
}
else
{
struct in_addr addr; // network byte order
if(inet_aton(tunif.ifaddr, &addr) == 0)
{
llarp::LogError(Name(),
" failed to set up tun interface, cant parse ",
tunif.ifaddr);
return false;
}
}
huint32_t ip;
if(ip.FromString(tunif.ifaddr))
{
m_OurIP = net::IPPacket::ExpandV4(ip);
m_OurRange.netmask_bits = netmask_ipv6_bits(tunif.netmask + 96);
}
else if(m_OurIP.FromString(tunif.ifaddr))
{
m_OurRange.netmask_bits = netmask_ipv6_bits(tunif.netmask);
}
llarp::Addr lAddr(tunif.ifaddr);
m_OurIP = lAddr.xtohl();
m_NextIP = m_OurIP;
m_OurRange.netmask_bits = netmask_ipv4_bits(tunif.netmask);
m_OurRange.addr = m_OurIP;
m_MaxIP = m_OurIP | (~m_OurRange.netmask_bits);
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr);
m_NextIP = m_OurIP;
m_OurRange.addr = m_OurIP;
m_MaxIP = m_OurIP | (~m_OurRange.netmask_bits);
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ",
m_OurIP);
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ",
m_OurRange);
MapAddress(m_Identity.pub.Addr(), m_OurIP, IsSNode());
if(m_OnUp)
{
@ -661,20 +698,30 @@ namespace llarp
void
TunEndpoint::FlushSend()
{
m_UserToNetworkPktQueue.Process([&](net::IPv4Packet &pkt) {
m_UserToNetworkPktQueue.Process([&](net::IPPacket &pkt) {
std::function< bool(const llarp_buffer_t &) > sendFunc;
auto itr = m_IPToAddr.find(pkt.dst());
huint128_t dst;
if(pkt.IsV4())
dst = net::IPPacket::ExpandV4(pkt.dstv4());
else
dst = pkt.dstv6();
auto itr = m_IPToAddr.find(dst);
if(itr == m_IPToAddr.end())
{
if(m_Exit && !llarp::IsIPv4Bogon(pkt.dst()))
if(m_Exit && pkt.IsV4() && !llarp::IsIPv4Bogon(pkt.dstv4()))
{
pkt.UpdateIPv4PacketOnDst({0}, pkt.dst());
pkt.UpdateV4Address({0}, pkt.dstv4());
m_Exit->QueueUpstreamTraffic(std::move(pkt),
llarp::routing::ExitPadSize);
}
else
llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst());
return true;
{
llarp::LogWarn(Name(), " has no endpoint for ", dst);
llarp::DumpBuffer(pkt.ConstBuffer());
}
return;
}
if(m_SNodes.at(itr->second))
@ -684,25 +731,26 @@ namespace llarp
}
else
{
sendFunc =
std::bind(&TunEndpoint::SendToServiceOrQueue, this,
service::Address(itr->second.as_array()),
std::placeholders::_1, service::eProtocolTraffic);
sendFunc = std::bind(&TunEndpoint::SendToServiceOrQueue, this,
service::Address(itr->second.as_array()),
std::placeholders::_1, pkt.ServiceProtocol());
}
// prepare packet for insertion into network
// this includes clearing IP addresses, recalculating checksums, etc
pkt.UpdateIPv4PacketOnSrc();
if(pkt.IsV4())
pkt.UpdateV4Address({0}, {0});
else
pkt.UpdateV6Address({0}, {0});
if(sendFunc && sendFunc(pkt.Buffer()))
return true;
return;
llarp::LogWarn(Name(), " did not flush packets");
return true;
});
}
bool
TunEndpoint::HandleWriteIPPacket(const llarp_buffer_t &b,
std::function< huint32_t(void) > getFromIP)
TunEndpoint::HandleWriteIPPacket(
const llarp_buffer_t &b, std::function< huint128_t(void) > getFromIP)
{
// llarp::LogInfo("got packet from ", msg->sender.Addr());
auto themIP = getFromIP();
@ -710,7 +758,7 @@ namespace llarp
auto usIP = m_OurIP;
ManagedBuffer buf(b);
return m_NetworkToUserPktQueue.EmplaceIf(
[buf, themIP, usIP](net::IPv4Packet &pkt) -> bool {
[buf, themIP, usIP](net::IPPacket &pkt) -> bool {
// load
if(!pkt.Load(buf))
return false;
@ -720,32 +768,39 @@ namespace llarp
// - packets with weird src/dst addresses
// (0.0.0.0/8 but not 0.0.0.0)
// - packets with 0 src but non-0 dst and oposite
auto hdr = pkt.Header();
if(pkt.sz < sizeof(*hdr) || hdr->version != 4
|| (hdr->saddr != 0 && *(byte_t *)&(hdr->saddr) == 0)
|| (hdr->daddr != 0 && *(byte_t *)&(hdr->daddr) == 0)
|| ((hdr->saddr == 0) != (hdr->daddr == 0)))
if(pkt.IsV4())
{
return false;
auto hdr = pkt.Header();
if(pkt.sz < sizeof(*hdr)
|| (hdr->saddr != 0 && *(byte_t *)&(hdr->saddr) == 0)
|| (hdr->daddr != 0 && *(byte_t *)&(hdr->daddr) == 0)
|| ((hdr->saddr == 0) != (hdr->daddr == 0)))
{
return false;
}
pkt.UpdateV4Address(net::IPPacket::TruncateV6(themIP), net::IPPacket::TruncateV6(usIP));
}
else if(pkt.IsV6())
{
if(pkt.srcv6() != huint128_t{0} || pkt.dstv6() != huint128_t{0})
return false;
pkt.UpdateV6Address(themIP, usIP);
}
// update packet to use proper addresses, recalc checksums
pkt.UpdateIPv4PacketOnDst(themIP, usIP);
return true;
});
}
huint32_t
huint128_t
TunEndpoint::GetIfAddr() const
{
return m_OurIP;
}
huint32_t
huint128_t
TunEndpoint::ObtainIPForAddr(const AlignedBuffer< 32 > &addr, bool snode)
{
llarp_time_t now = Now();
huint32_t nextIP = {0};
llarp_time_t now = Now();
huint128_t nextIP = {0};
AlignedBuffer< 32 > ident(addr);
{
// previously allocated address
@ -779,7 +834,7 @@ namespace llarp
// we are full
// expire least active ip
// TODO: prevent DoS
std::pair< huint32_t, llarp_time_t > oldest = {huint32_t{0}, 0};
std::pair< huint128_t, llarp_time_t > oldest = {huint128_t{0}, 0};
// find oldest entry
auto itr = m_IPActivity.begin();
@ -808,19 +863,20 @@ namespace llarp
}
bool
TunEndpoint::HasRemoteForIP(huint32_t ip) const
TunEndpoint::HasRemoteForIP(huint128_t ip) const
{
return m_IPToAddr.find(ip) != m_IPToAddr.end();
}
void
TunEndpoint::MarkIPActive(huint32_t ip)
TunEndpoint::MarkIPActive(huint128_t ip)
{
llarp::LogDebug(Name(), " address " , ip, " is active");
m_IPActivity[ip] = std::max(Now(), m_IPActivity[ip]);
}
void
TunEndpoint::MarkIPActiveForever(huint32_t ip)
TunEndpoint::MarkIPActiveForever(huint128_t ip)
{
m_IPActivity[ip] = std::numeric_limits< uint64_t >::max();
}
@ -844,7 +900,7 @@ namespace llarp
self->m_Exit->FlushDownstream();
}
// flush network to user
self->m_NetworkToUserPktQueue.Process([tun](net::IPv4Packet &pkt) {
self->m_NetworkToUserPktQueue.Process([tun](net::IPPacket &pkt) {
if(!llarp_ev_tun_async_write(tun, pkt.Buffer()))
llarp::LogWarn("packet dropped");
});
@ -857,9 +913,7 @@ namespace llarp
TunEndpoint *self = static_cast< TunEndpoint * >(tun->user);
ManagedBuffer buf(b);
if(!self->m_UserToNetworkPktQueue.EmplaceIf(
[buf](net::IPv4Packet &pkt) -> bool {
return pkt.Load(buf) && pkt.Header()->version == 4;
}))
[buf](net::IPPacket &pkt) -> bool { return pkt.Load(buf); }))
{
#if defined(DEBUG) || !defined(RELEASE_MOTTO)
llarp::LogInfo("invalid pkt");

@ -46,6 +46,9 @@ namespace llarp
std::unordered_map< std::string, std::string >
NotifyParams() const override;
bool
SupportsV6() const override;
bool
ShouldHookDNSMessage(const dns::Message& msg) const override;
@ -58,7 +61,7 @@ namespace llarp
TickTun(llarp_time_t now);
bool
MapAddress(const service::Address& remote, huint32_t ip, bool SNode);
MapAddress(const service::Address& remote, huint128_t ip, bool SNode);
bool
Start() override;
@ -81,11 +84,11 @@ namespace llarp
/// handle inbound traffic
bool
HandleWriteIPPacket(const llarp_buffer_t& buf,
std::function< huint32_t(void) > getFromIP) override;
std::function< huint128_t(void) > getFromIP) override;
/// queue outbound packet to the world
bool
QueueOutboundTraffic(llarp::net::IPv4Packet&& pkt);
QueueOutboundTraffic(llarp::net::IPPacket&& pkt);
/// we have a resolvable ip address
bool
@ -95,11 +98,11 @@ namespace llarp
}
/// get the local interface's address
huint32_t
huint128_t
GetIfAddr() const override;
bool
HasLocalIP(const huint32_t& ip) const;
HasLocalIP(const huint128_t& ip) const;
llarp_tun_io tunif;
std::unique_ptr< llarp_fd_promise > Promise;
@ -124,7 +127,7 @@ namespace llarp
/// get a key for ip address
template < typename Addr >
Addr
ObtainAddrForIP(huint32_t ip, bool isSNode)
ObtainAddrForIP(huint128_t ip, bool isSNode)
{
auto itr = m_IPToAddr.find(ip);
if(itr == m_IPToAddr.end() || m_SNodes[itr->second] != isSNode)
@ -145,7 +148,7 @@ namespace llarp
}
/// get ip address for key unconditionally
huint32_t
huint128_t
ObtainIPForAddr(const AlignedBuffer< 32 >& addr,
bool serviceNode) override;
@ -158,33 +161,33 @@ namespace llarp
protected:
using PacketQueue_t = llarp::util::CoDelQueue<
net::IPv4Packet, net::IPv4Packet::GetTime, net::IPv4Packet::PutTime,
net::IPv4Packet::CompareOrder, net::IPv4Packet::GetNow >;
net::IPPacket, net::IPPacket::GetTime, net::IPPacket::PutTime,
net::IPPacket::CompareOrder, net::IPPacket::GetNow >;
/// queue for sending packets over the network from us
PacketQueue_t m_UserToNetworkPktQueue;
/// queue for sending packets to user from network
PacketQueue_t m_NetworkToUserPktQueue;
/// return true if we have a remote loki address for this ip address
bool
HasRemoteForIP(huint32_t ipv4) const;
HasRemoteForIP(huint128_t ipv4) const;
/// mark this address as active
void
MarkIPActive(huint32_t ip);
MarkIPActive(huint128_t ip);
/// mark this address as active forever
void
MarkIPActiveForever(huint32_t ip);
MarkIPActiveForever(huint128_t ip);
/// flush ip packets
virtual void
FlushSend();
/// maps ip to key (host byte order)
std::unordered_map< huint32_t, AlignedBuffer< 32 >, huint32_t::Hash >
std::unordered_map< huint128_t, AlignedBuffer< 32 >, huint128_t::Hash >
m_IPToAddr;
/// maps key to ip (host byte order)
std::unordered_map< AlignedBuffer< 32 >, huint32_t,
std::unordered_map< AlignedBuffer< 32 >, huint128_t,
AlignedBuffer< 32 >::Hash >
m_AddrToIP;
@ -199,10 +202,29 @@ namespace llarp
{
ManagedBuffer copy{buf};
return m_NetworkToUserPktQueue.EmplaceIf(
[&](llarp::net::IPv4Packet& pkt) -> bool {
[&](llarp::net::IPPacket& pkt) -> bool {
if(!pkt.Load(copy.underlying))
return false;
pkt.UpdateIPv4PacketOnDst(pkt.src(), m_OurIP);
if(SupportsV6())
{
if(pkt.IsV4())
{
pkt.UpdateV6Address(net::IPPacket::ExpandV4(pkt.srcv4()),
m_OurIP);
}
else
{
pkt.UpdateV6Address(pkt.srcv6(), m_OurIP);
}
}
else
{
if(pkt.IsV4())
pkt.UpdateV4Address(pkt.srcv4(),
net::IPPacket::TruncateV6(m_OurIP));
else
return false;
}
return true;
});
}
@ -215,7 +237,7 @@ namespace llarp
{
if(ctx)
{
huint32_t ip = ObtainIPForAddr(addr, snode);
huint128_t ip = ObtainIPForAddr(addr, snode);
query->AddINReply(ip, sendIPv6);
}
else
@ -233,14 +255,14 @@ namespace llarp
std::shared_ptr< dns::Proxy > m_Resolver;
/// maps ip address to timestamp last active
std::unordered_map< huint32_t, llarp_time_t, huint32_t::Hash >
std::unordered_map< huint128_t, llarp_time_t, huint128_t::Hash >
m_IPActivity;
/// our ip address (host byte order)
huint32_t m_OurIP;
huint128_t m_OurIP;
/// next ip address to allocate (host byte order)
huint32_t m_NextIP;
huint128_t m_NextIP;
/// highest ip address to allocate (host byte order)
huint32_t m_MaxIP;
huint128_t m_MaxIP;
/// our ip range we are using
llarp::IPRange m_OurRange;
/// upstream dns resolver list
@ -249,6 +271,8 @@ namespace llarp
llarp::Addr m_LocalResolverAddr;
/// list of strict connect addresses for hooks
std::vector< llarp::Addr > m_StrictConnectAddrs;
/// use v6?
bool m_UseV6;
};
} // namespace handlers
} // namespace llarp

@ -15,8 +15,61 @@ namespace llarp
{
namespace net
{
huint128_t
IPPacket::In6ToHUInt(in6_addr addr)
{
#if __BYTE_ORDER == __BIG_ENDIAN
return huint128_t{addr.s6_addr32[0]}
| (huint128_t{addr.s6_addr32[1]} << 32)
| (huint128_t{addr.s6_addr32[2]} << 64)
| (huint128_t{addr.s6_addr32[3]} << 96);
#else
return huint128_t{ntohl(addr.s6_addr32[3])}
| (huint128_t{ntohl(addr.s6_addr32[2])} << 32)
| (huint128_t{ntohl(addr.s6_addr32[1])} << 64)
| (huint128_t{ntohl(addr.s6_addr32[0])} << 96);
#endif
}
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
IPPacket::srcv6() const
{
return In6ToHUInt(HeaderV6()->srcaddr);
}
huint128_t
IPPacket::dstv6() const
{
return In6ToHUInt(HeaderV6()->dstaddr);
}
bool
IPv4Packet::Load(const llarp_buffer_t &pkt)
IPPacket::Load(const llarp_buffer_t &pkt)
{
if(pkt.sz > sizeof(buf))
return false;
@ -26,17 +79,37 @@ namespace llarp
}
llarp_buffer_t
IPv4Packet::ConstBuffer() const
IPPacket::ConstBuffer() const
{
return {buf, sz};
}
llarp_buffer_t
IPv4Packet::Buffer()
IPPacket::Buffer()
{
return {buf, sz};
}
huint32_t
IPPacket::srcv4() const
{
return huint32_t{ntohl(Header()->saddr)};
}
huint32_t
IPPacket::dstv4() const
{
return huint32_t{ntohl(Header()->daddr)};
}
void
IPPacket::UpdateV6Address(huint128_t src, huint128_t dst)
{
auto hdr = HeaderV6();
hdr->srcaddr = HUIntToIn6(src);
hdr->dstaddr = HUIntToIn6(dst);
}
#if 0
static uint32_t
ipchksum_pseudoIPv4(nuint32_t src_ip, nuint32_t dst_ip, uint8_t proto,
@ -140,8 +213,9 @@ namespace llarp
}
void
IPv4Packet::UpdateIPv4PacketOnDst(huint32_t newSrcIP, huint32_t newDstIP)
IPPacket::UpdateV4Address(huint32_t newSrcIP, huint32_t newDstIP)
{
llarp::LogDebug("set src=", newSrcIP, " dst=", newDstIP);
auto hdr = Header();
auto oSrcIP = nuint32_t{hdr->saddr};
@ -227,9 +301,9 @@ namespace llarp
// if(check->n == 0x0000)
// check->n = 0xFFff;
}
/*
void
IPv4Packet::UpdateIPv4PacketOnSrc()
IPacket::UpdateIPv4PacketOnSrc()
{
auto hdr = Header();
@ -269,5 +343,6 @@ namespace llarp
hdr->saddr = 0;
hdr->daddr = 0;
}
*/
} // namespace net
} // namespace llarp

@ -74,7 +74,17 @@ typedef struct ip_hdr
#endif
struct ipv6_header
{
unsigned char version : 4;
unsigned char pad_small : 4;
uint8_t pad [7];
in6_addr srcaddr;
in6_addr dstaddr;
};
#include <memory>
#include <service/protocol.hpp>
struct llarp_ev_loop;
@ -82,28 +92,21 @@ namespace llarp
{
namespace net
{
/// a network layer packet
struct NetPacket
/// an Packet
struct IPPacket
{
virtual ~NetPacket(){};
static huint128_t
In6ToHUInt(in6_addr addr);
virtual byte_t
Version() const = 0;
static in6_addr
HUIntToIn6(huint128_t x);
virtual byte_t
IPProto() const = 0;
static huint128_t
ExpandV4(huint32_t x);
virtual llarp_buffer_t
Buffer() = 0;
virtual llarp_buffer_t
ConstBuffer() const = 0;
};
static huint32_t
TruncateV6(huint128_t x);
/// an IPv4 Packet
/// TODO: make it implement NetPacket
struct IPv4Packet
{
static constexpr size_t MaxSize = 1500;
llarp_time_t timestamp;
size_t sz;
@ -121,7 +124,7 @@ namespace llarp
struct GetTime
{
llarp_time_t
operator()(const IPv4Packet& pkt) const
operator()(const IPPacket& pkt) const
{
return pkt.timestamp;
}
@ -134,7 +137,7 @@ namespace llarp
{
}
void
operator()(IPv4Packet& pkt) const
operator()(IPPacket& pkt) const
{
pkt.timestamp = llarp_ev_loop_time_now_ms(loop);
}
@ -156,7 +159,7 @@ namespace llarp
struct CompareSize
{
bool
operator()(const IPv4Packet& left, const IPv4Packet& right)
operator()(const IPPacket& left, const IPPacket& right)
{
return left.sz < right.sz;
}
@ -165,7 +168,7 @@ namespace llarp
struct CompareOrder
{
bool
operator()(const IPv4Packet& left, const IPv4Packet& right)
operator()(const IPPacket& left, const IPPacket& right)
{
return left.timestamp < right.timestamp;
}
@ -183,37 +186,70 @@ namespace llarp
return (ip_header*)&buf[0];
}
inline huint32_t
src()
inline ipv6_header*
HeaderV6()
{
return (ipv6_header*)&buf[0];
}
inline const ipv6_header*
HeaderV6() const
{
return huint32_t{ntohl(Header()->saddr)};
return (ipv6_header*)&buf[0];
}
inline huint32_t
dst()
inline int
Version() const
{
return huint32_t{ntohl(Header()->daddr)};
return Header()->version;
}
inline void
src(huint32_t ip)
inline bool
IsV4() const
{
Header()->saddr = htonl(ip.h);
return Version() == 4;
}
inline void
dst(huint32_t ip)
inline bool
IsV6() const
{
Header()->daddr = htonl(ip.h);
return Version() == 6;
}
// update ip packet (after packet gets out of network)
inline service::ProtocolType
ServiceProtocol() const
{
if(IsV4())
return service::eProtocolTrafficV4;
else if(IsV6())
return service::eProtocolTrafficV6;
else
return service::eProtocolControl;
}
huint128_t
srcv6() const;
huint128_t
dstv6() const;
huint32_t
srcv4() const;
huint32_t
dstv4() const;
huint128_t
src4to6() const;
huint128_t
dst4to6() const;
void
UpdateIPv4PacketOnDst(huint32_t newSrcIP, huint32_t newDstIP);
UpdateV4Address(huint32_t src, huint32_t dst);
// update ip packet (before packet gets inserted into network)
void
UpdateIPv4PacketOnSrc();
UpdateV6Address(huint128_t src, huint128_t dst);
};
} // namespace net

@ -13,6 +13,7 @@
#endif
#include <net/net_addr.hpp>
#include <net/ip.hpp>
#include <util/logger.hpp>
#include <util/str.hpp>
@ -1010,6 +1011,37 @@ namespace llarp
return IsBogon(host);
}
bool
IPRange::ContainsV4(const huint32_t& ip) const
{
return Contains(net::IPPacket::ExpandV4(ip));
}
std::string
IPRange::ToString() const
{
char buf[INET6_ADDRSTRLEN + 1] = {0};
std::string str;
in6_addr inaddr;
size_t numset = 0;
absl::uint128 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_ipv4(byte_t a, byte_t b, byte_t c, byte_t d, byte_t mask)
{
return IPRange{net::IPPacket::ExpandV4(ipaddr_ipv4_bits(a, b, c, d)),
netmask_ipv6_bits(mask + 96)};
}
bool
IsIPv4Bogon(const huint32_t& addr)
{
@ -1024,7 +1056,7 @@ namespace llarp
iprange_ipv4(224, 0, 0, 0, 4), iprange_ipv4(240, 0, 0, 0, 4)};
for(const auto& bogon : bogonRanges)
{
if(bogon.Contains(addr))
if(bogon.ContainsV4(addr))
{
#if defined(TESTNET)
return false;

@ -1,6 +1,7 @@
#ifndef LLARP_NET_HPP
#define LLARP_NET_HPP
#include <absl/numeric/int128.h>
#include <net/address_info.hpp>
#include <net/net_int.hpp>
#include <net/net.h>
@ -59,16 +60,19 @@ namespace llarp
{
struct IPRange
{
huint32_t addr;
huint32_t netmask_bits;
huint128_t addr;
huint128_t netmask_bits;
/// return true if ip is contained in this ip range
bool
Contains(const huint32_t& ip) const
Contains(const huint128_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)
{
@ -76,13 +80,27 @@ namespace llarp
}
std::string
ToString() const
{
return addr.ToString() + "/"
+ std::to_string(llarp::bits::count_bits(netmask_bits.h));
}
ToString() const;
};
huint128_t
ExpandV4(huint32_t x);
/// get a netmask with the higest numset bits set
constexpr huint128_t
__netmask_ipv6_bits(uint32_t numset)
{
return (128 - numset)
? (huint128_t{1} << numset) | __netmask_ipv6_bits(numset + 1)
: huint128_t{0};
}
constexpr huint128_t
netmask_ipv6_bits(uint32_t numset)
{
return __netmask_ipv6_bits(128 - numset);
}
/// get a netmask with the higest numset bits set
constexpr uint32_t
__netmask_ipv4_bits(uint32_t numset)
@ -90,7 +108,7 @@ namespace llarp
return (32 - numset) ? (1 << numset) | __netmask_ipv4_bits(numset + 1) : 0;
}
/// get an ipv4 netmask given some /N range
/// get a netmask given some /N range
constexpr huint32_t
netmask_ipv4_bits(uint32_t num)
{
@ -107,11 +125,8 @@ namespace llarp
#endif
}
constexpr IPRange
iprange_ipv4(byte_t a, byte_t b, byte_t c, byte_t d, byte_t mask)
{
return IPRange{ipaddr_ipv4_bits(a, b, c, d), netmask_ipv4_bits(mask)};
}
IPRange
iprange_ipv4(byte_t a, byte_t b, byte_t c, byte_t d, byte_t mask);
bool
IsIPv4Bogon(const huint32_t& addr);

@ -1,5 +1,5 @@
#include <net/net_int.hpp>
#include <net/ip.hpp>
#include <string>
namespace llarp
@ -15,6 +15,15 @@ namespace llarp
c[10] = 0xff;
}
template <>
void
huint128_t::ToV6(V6Container& c)
{
c.resize(16);
const in6_addr addr = net::IPPacket::HUIntToIn6(*this);
std::copy_n(addr.s6_addr, 16, c.begin());
}
template <>
std::string
huint32_t::ToString() const
@ -25,6 +34,40 @@ namespace llarp
return "";
return tmp;
}
template <>
std::string
huint128_t::ToString() const
{
absl::uint128 addr = ntoh128(h);
char tmp[INET6_ADDRSTRLEN] = {0};
if(!inet_ntop(AF_INET6, (void*)&addr, tmp, sizeof(tmp)))
return "";
return tmp;
}
template <>
bool
huint32_t::FromString(const std::string& str)
{
uint32_t n;
if(!inet_pton(AF_INET, str.c_str(), &n))
return false;
h = ntohl(n);
return true;
}
template <>
bool
huint128_t::FromString(const std::string& str)
{
absl::uint128 i;
if(!inet_pton(AF_INET6, str.c_str(), &i))
return false;
h = ntoh128(i);
return true;
}
template <>
std::string
nuint32_t::ToString() const

@ -19,6 +19,9 @@
#include <util/endian.hpp>
#include <vector>
#include <absl/numeric/int128.h>
#include <absl/hash/hash.h>
namespace llarp
{
template < typename UInt_t >
@ -28,25 +31,33 @@ namespace llarp
constexpr huint_t operator&(huint_t x) const
{
return huint_t{UInt_t(h & x.h)};
return huint_t{UInt_t{h & x.h}};
}
constexpr huint_t
operator|(huint_t x) const
{
return huint_t{UInt_t(h | x.h)};
return huint_t{UInt_t{h | x.h}};
}
constexpr huint_t
operator^(huint_t x) const
{
return huint_t{UInt_t(h ^ x.h)};
return huint_t{UInt_t{h ^ x.h}};
}
constexpr huint_t
operator~() const
{
return huint_t{UInt_t(~h)};
return huint_t{UInt_t{~h}};
}
constexpr huint_t
operator<<(int n) const
{
UInt_t v{h};
v <<= n;
return huint_t{v};
}
inline huint_t
@ -69,20 +80,26 @@ namespace llarp
return h < x.h;
}
constexpr bool
operator!=(huint_t x) const
{
return h != x.h;
}
constexpr bool
operator==(huint_t x) const
{
return h == x.h;
}
struct Hash
using Hash = absl::Hash< huint_t< UInt_t > >;
template < typename H >
friend H
AbslHashValue(H h, const huint_t< UInt_t >& i)
{
inline size_t
operator()(huint_t x) const
{
return std::hash< UInt_t >{}(x.h);
}
};
return H::combine(std::move(h), i.h);
}
using V6Container = std::vector< uint8_t >;
void
@ -91,6 +108,9 @@ namespace llarp
std::string
ToString() const;
bool
FromString(const std::string&);
friend std::ostream&
operator<<(std::ostream& out, const huint_t& i)
{
@ -98,8 +118,9 @@ namespace llarp
}
};
using huint32_t = huint_t< uint32_t >;
using huint16_t = huint_t< uint16_t >;
using huint32_t = huint_t< uint32_t >;
using huint16_t = huint_t< uint16_t >;
using huint128_t = huint_t< absl::uint128 >;
template < typename UInt_t >
struct nuint_t
@ -177,8 +198,9 @@ namespace llarp
}
};
using nuint32_t = nuint_t< uint32_t >;
using nuint16_t = nuint_t< uint16_t >;
using nuint32_t = nuint_t< uint32_t >;
using nuint16_t = nuint_t< uint16_t >;
using nuint128_t = nuint_t< absl::uint128 >;
static inline nuint32_t
xhtonl(huint32_t x)

@ -14,7 +14,8 @@ namespace llarp
const Identity& localident,
const PQPubKey& introsetPubKey,
const Introduction& remote,
IDataHandler* h, const ConvoTag& t)
IDataHandler* h, const ConvoTag& t,
ProtocolType proto)
: logic(l)
, remote(r)
, m_LocalIdentity(localident)
@ -23,6 +24,7 @@ namespace llarp
, handler(h)
, tag(t)
{
msg.proto = proto;
}
void
@ -69,8 +71,6 @@ namespace llarp
self->msg.sender = self->m_LocalIdentity.pub;
// set version
self->msg.version = LLARP_PROTO_VERSION;
// set protocol
self->msg.proto = eProtocolTraffic;
// encrypt and sign
if(self->frame.EncryptAndSign(self->msg, K, self->m_LocalIdentity))
self->logic->queue_job({self, &Result});

@ -30,7 +30,7 @@ namespace llarp
const Identity& localident,
const PQPubKey& introsetPubKey,
const Introduction& remote, IDataHandler* h,
const ConvoTag& t);
const ConvoTag& t, ProtocolType proto);
static void
Result(void* user);

@ -154,7 +154,7 @@ namespace llarp
bool
Context::FindBestAddressFor(const AlignedBuffer< 32 > &addr, bool isSNode,
huint32_t &ip)
huint128_t &ip)
{
auto itr = m_Endpoints.begin();
while(itr != m_Endpoints.end())

@ -33,7 +33,7 @@ namespace llarp
bool
FindBestAddressFor(const AlignedBuffer< 32 > &addr, bool isSNode,
huint32_t &);
huint128_t &);
/// function visitor returns false to prematurely break iteration
void

@ -856,7 +856,7 @@ namespace llarp
bool
Endpoint::ProcessDataMessage(std::shared_ptr< ProtocolMessage > msg)
{
if(msg->proto == eProtocolTraffic)
if(msg->proto == eProtocolTrafficV4 || msg->proto == eProtocolTrafficV6)
{
util::Lock l(&m_InboundTrafficQueueMutex);
m_InboundTrafficQueue.emplace(msg);
@ -1009,7 +1009,7 @@ namespace llarp
auto session = std::make_shared< exit::SNodeSession >(
snode,
std::bind(&Endpoint::HandleWriteIPPacket, this, _1,
[themIP]() -> huint32_t { return themIP; }),
[themIP]() -> huint128_t { return themIP; }),
m_Router, m_NumPaths, numHops, false, ShouldBundleRC());
m_SNodeSessions.emplace(snode, session);
}
@ -1033,7 +1033,7 @@ namespace llarp
Endpoint::SendToSNodeOrQueue(const RouterID& addr,
const llarp_buffer_t& buf)
{
auto pkt = std::make_shared< net::IPv4Packet >();
auto pkt = std::make_shared< net::IPPacket >();
if(!pkt->Load(buf))
return false;
EnsurePathToSNode(addr, [pkt](RouterID, exit::BaseSession_ptr s) {
@ -1055,7 +1055,7 @@ namespace llarp
{
const auto& msg = m_InboundTrafficQueue.top();
llarp_buffer_t buf(msg->payload);
HandleWriteIPPacket(buf, [&]() -> huint32_t {
HandleWriteIPPacket(buf, [&]() -> huint128_t {
return ObtainIPForAddr(msg->sender.Addr(), false);
});
m_InboundTrafficQueue.pop();

@ -81,10 +81,10 @@ namespace llarp
}
/// get our ifaddr if it is set
virtual huint32_t
virtual huint128_t
GetIfAddr() const
{
return huint32_t{0};
return huint128_t{0};
}
virtual void
@ -151,7 +151,7 @@ namespace llarp
HandleHiddenServiceFrame(path::Path_ptr p,
const service::ProtocolFrame& msg);
virtual huint32_t
virtual huint128_t
ObtainIPForAddr(const AlignedBuffer< 32 >& addr, bool serviceNode) = 0;
virtual bool
@ -173,7 +173,7 @@ namespace llarp
virtual bool
HandleWriteIPPacket(const llarp_buffer_t& pkt,
std::function< huint32_t(void) > getFromIP) = 0;
std::function< huint128_t(void) > getFromIP) = 0;
bool
ProcessDataMessage(std::shared_ptr< ProtocolMessage > msg);
@ -313,6 +313,9 @@ namespace llarp
/// parent context that owns this endpoint
Context* const context;
virtual bool
SupportsV6() const = 0;
void
RegenAndPublishIntroSet(llarp_time_t now, bool forceRebuild = false);

@ -160,13 +160,12 @@ namespace llarp
currentConvoTag.Randomize();
AsyncKeyExchange* ex = new AsyncKeyExchange(
m_Endpoint->RouterLogic(), remoteIdent, m_Endpoint->GetIdentity(),
currentIntroSet.K, remoteIntro, m_DataHandler, currentConvoTag);
currentIntroSet.K, remoteIntro, m_DataHandler, currentConvoTag, t);
ex->hook =
std::bind(&OutboundContext::Send, this, std::placeholders::_1, path);
ex->msg.PutBuffer(payload);
ex->msg.proto = t;
ex->msg.introReply = path->intro;
ex->frame.F = ex->msg.introReply.pathID;
llarp_threadpool_queue_job(m_Endpoint->CryptoWorker(),

@ -33,8 +33,9 @@ namespace llarp
using ProtocolType = uint64_t;
constexpr ProtocolType eProtocolControl = 0UL;
constexpr ProtocolType eProtocolTraffic = 1UL;
constexpr ProtocolType eProtocolControl = 0UL;
constexpr ProtocolType eProtocolTrafficV4 = 1UL;
constexpr ProtocolType eProtocolTrafficV6 = 2UL;
/// inner message
struct ProtocolMessage
@ -42,7 +43,7 @@ namespace llarp
ProtocolMessage(const ConvoTag& tag);
ProtocolMessage();
~ProtocolMessage();
ProtocolType proto = eProtocolTraffic;
ProtocolType proto = eProtocolTrafficV4;
llarp_time_t queued = 0;
std::vector< byte_t > payload;
Introduction introReply;

@ -6,6 +6,7 @@
#include <numeric>
#include <type_traits>
#include <limits>
#include <absl/numeric/int128.h>
namespace llarp
{

@ -5,6 +5,7 @@
#include <inttypes.h>
#include <string.h>
#include <absl/numeric/int128.h>
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/endian.h>
@ -189,4 +190,19 @@ htole64buf(void *buf, uint64_t big64)
htobuf64(buf, htole64(big64));
}
inline absl::uint128
ntoh128(absl::uint128 i)
{
#if __BYTE_ORDER == __BIG_ENDIAN
return i;
#else
uint64_t *ptr = (uint64_t *)&i;
absl::uint128 ret;
uint64_t *retptr = (uint64_t *)&ret;
htobe64buf(retptr, ptr[1]);
htobe64buf(retptr + 1, ptr[0]);
return ret;
#endif
}
#endif

@ -2,27 +2,63 @@
#include <net/net.hpp>
#include <net/net_inaddr.hpp>
#include <net/net_int.hpp>
#include <net/ip.hpp>
struct TestNet : public ::testing::Test
{
};
TEST_F(TestNet, TestIn6AddrFromString)
{
llarp::huint128_t ip;
ASSERT_TRUE(ip.FromString("fc00::1"));
}
TEST_F(TestNet, TestIn6AddrFromStringFail)
{
llarp::huint128_t ip;
ASSERT_FALSE(ip.FromString("10.1.1.1"));
}
TEST_F(TestNet, TestIn6AddrToHUIntLoopback)
{
llarp::huint128_t loopback = {0};
ASSERT_TRUE(loopback.FromString("::1"));
in6_addr addr = IN6ADDR_LOOPBACK_INIT;
auto huint = llarp::net::IPPacket::In6ToHUInt(addr);
ASSERT_EQ(huint, loopback);
}
TEST_F(TestNet, TestIn6AddrToHUInt)
{
llarp::huint128_t huint_parsed = {0};
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 } } };
auto huint = llarp::net::IPPacket::In6ToHUInt(addr);
ASSERT_EQ(huint, huint_parsed);
huint_parsed.h ++;
ASSERT_NE(huint, huint_parsed);
}
TEST_F(TestNet, TestRangeContains8)
{
ASSERT_TRUE(llarp::iprange_ipv4(10, 0, 0, 1, 8)
.Contains(llarp::ipaddr_ipv4_bits(10, 40, 11, 6)));
.ContainsV4(llarp::ipaddr_ipv4_bits(10, 40, 11, 6)));
}
TEST_F(TestNet, TestRangeContains24)
{
ASSERT_TRUE(llarp::iprange_ipv4(10, 200, 0, 1, 24)
.Contains(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
.ContainsV4(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
}
TEST_F(TestNet, TestRangeContainsFail)
{
ASSERT_TRUE(!llarp::iprange_ipv4(192, 168, 0, 1, 24)
.Contains(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
.ContainsV4(llarp::ipaddr_ipv4_bits(10, 200, 0, 253)));
}
TEST_F(TestNet, TestIPv4Netmask)

@ -188,14 +188,50 @@ tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t bits)
return 0;
}
struct in6_ifreq {
struct in6_addr ifr6_addr;
__u32 ifr6_prefixlen;
unsigned int ifr6_ifindex;
};
int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s6, uint32_t bits)
{
(void)dev;
(void)s6;
(void)bits;
tuntap_log(TUNTAP_LOG_NOTICE, "IPv6 is not implemented on your system");
return -1;
struct ifreq ifr;
struct sockaddr_in6 sai;
int sockfd;
struct in6_ifreq ifr6;
sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
if (sockfd == -1) {
return -1;
}
/* get interface name */
strncpy(ifr.ifr_name, dev->if_name, IFNAMSIZ);
memset(&sai, 0, sizeof(struct sockaddr));
sai.sin6_family = AF_INET6;
sai.sin6_port = 0;
memcpy((char *) &ifr6.ifr6_addr, (char *) s6,
sizeof(struct in6_addr));
if (ioctl(sockfd, SIOGIFINDEX, &ifr) < 0) {
perror("SIOGIFINDEX");
close(sockfd);
return -1;
}
ifr6.ifr6_ifindex = ifr.ifr_ifindex;
ifr6.ifr6_prefixlen = bits;
if (ioctl(sockfd, SIOCSIFADDR, &ifr6) < 0) {
perror("SIOCSIFADDR");
close(sockfd);
return -1;
}
close(sockfd);
return 0;
}
int

@ -161,7 +161,7 @@ extern "C"
llarp::LogError("invalid ipv6 address: ", addr);
return -1;
}
return tuntap_sys_set_ipv6(dev, &baddr6, mask);
return tuntap_sys_set_ipv6(dev, &baddr6, netmask);
}
else if(errval == -1)
{

Loading…
Cancel
Save