Merge pull request #103 from majestrate/dev

merge in dnslib and fix setcap
pull/106/head
Jeff 6 years ago committed by GitHub
commit 2069ca403b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -423,8 +423,18 @@ if(WIN32)
set(UTP_SRC ${UTP_SRC} libutp/libutp_inet_ntop.cpp)
endif()
set(DNSLIB_SRC
llarp/dns/message.cpp
llarp/dns/name.cpp
llarp/dns/question.cpp
llarp/dns/rr.cpp
llarp/dns/serialize.cpp
llarp/dns/server.cpp
)
set(LIB_SRC
${DNSLIB_SRC}
${UTP_SRC}
llarp/address_info.cpp
llarp/bencode.cpp
@ -527,6 +537,7 @@ set(TEST_SRC
test/test_dns_unit.cpp
test/test_dnsc_unit.cpp
test/test_dnsd_unit.cpp
test/test_dnslib.cpp
test/test_llarp_queue.cpp
test/test_llarp_queue_manager.cpp
test/test_llarp_thread_pool.cpp

@ -10,7 +10,7 @@ prefix = $(DESTDIR)/usr/local
CC ?= cc
CXX ?= c++
SETCAP ?= which setcap && setcap cap_net_bind_service,cap_net_admin=+eip
SETCAP ?= which setcap && setcap cap_net_admin,cap_net_bind_service=+eip
SHADOW_ROOT ?= $(HOME)/.shadow
SHADOW_BIN=$(SHADOW_ROOT)/bin/shadow

@ -0,0 +1,5 @@
#include <llarp/dns/name.hpp>
#include <llarp/dns/rr.hpp>
#include <llarp/dns/serialize.hpp>
#include <llarp/dns/message.hpp>
#include <llarp/dns/server.hpp>

@ -0,0 +1,97 @@
#ifndef LLARP_DNS_MESSAGE_HPP
#define LLARP_DNS_MESSAGE_HPP
#include <llarp/dns/serialize.hpp>
#include <llarp/dns/rr.hpp>
#include <llarp/dns/question.hpp>
namespace llarp
{
namespace dns
{
using MsgID_t = uint16_t;
using Fields_t = uint16_t;
using Count_t = uint16_t;
struct MessageHeader : public Serialize
{
const static size_t Size = 12;
MessageHeader() = default;
MsgID_t id;
Fields_t fields;
Count_t qd_count;
Count_t an_count;
Count_t ns_count;
Count_t ar_count;
bool
Encode(llarp_buffer_t* buf) const override;
bool
Decode(llarp_buffer_t* buf) override;
bool
operator==(const MessageHeader& other) const
{
return id == other.id && fields == other.fields
&& qd_count == other.qd_count && an_count == other.an_count
&& ns_count == other.ns_count && ar_count == other.ar_count;
}
};
struct Message : public Serialize
{
Message(const MessageHeader& hdr);
Message(Message&& other);
Message(const Message& other);
void
UpdateHeader();
void
AddNXReply();
void
AddINReply(llarp::huint32_t addr);
void
AddAReply(std::string name);
bool
Encode(llarp_buffer_t* buf) const override;
bool
Decode(llarp_buffer_t* buf) override;
friend std::ostream&
operator<<(std::ostream& out, const Message& msg)
{
out << "[dns message id=" << std::hex << msg.hdr_id
<< " fields=" << msg.hdr_fields << " questions=[ ";
for(const auto& qd : msg.questions)
out << qd << ", ";
out << "] answers=[ ";
for(const auto& an : msg.answers)
out << an << ", ";
out << "] nameserver=[ ";
for(const auto& ns : msg.authorities)
out << ns << ", ";
out << "] additional=[ ";
for(const auto& ar : msg.additional)
out << ar << ", ";
return out << "]";
}
MsgID_t hdr_id;
Fields_t hdr_fields;
std::vector< Question > questions;
std::vector< ResourceRecord > answers;
std::vector< ResourceRecord > authorities;
std::vector< ResourceRecord > additional;
};
} // namespace dns
} // namespace llarp
#endif

@ -0,0 +1,28 @@
#ifndef LLARP_DNS_NAME_HPP
#define LLARP_DNS_NAME_HPP
#include <string>
#include <llarp/buffer.h>
#include <llarp/net_int.hpp>
namespace llarp
{
namespace dns
{
using Name_t = std::string;
/// decode name from buffer
bool
DecodeName(llarp_buffer_t* buf, Name_t& name);
/// encode name to buffer
bool
EncodeName(llarp_buffer_t* buf, const Name_t& name);
bool
DecodePTR(const Name_t& name, huint32_t& ip);
} // namespace dns
} // namespace llarp
#endif

@ -0,0 +1,4 @@
#ifndef LLARP_DNS_QUERY_HPP
#define LLARP_DNS_QUERY_HPP
#endif

@ -0,0 +1,46 @@
#ifndef LLARP_DNS_QUESTION_HPP
#define LLARP_DNS_QUESTION_HPP
#include <llarp/dns/serialize.hpp>
#include <llarp/dns/name.hpp>
#include <llarp/net_int.hpp>
namespace llarp
{
namespace dns
{
using QType_t = uint16_t;
using QClass_t = uint16_t;
struct Question : public Serialize
{
Question() = default;
Question(Question&& other);
Question(const Question& other);
bool
Encode(llarp_buffer_t* buf) const override;
bool
Decode(llarp_buffer_t* buf) override;
bool
operator==(const Question& other) const
{
return qname == other.qname && qtype == other.qtype
&& qclass == other.qclass;
}
friend std::ostream&
operator<<(std::ostream& out, const Question& q)
{
return out << "qname=" << q.qname << " qtype=" << (int)q.qtype
<< " qclass=" << (int)q.qclass;
}
Name_t qname;
QType_t qtype;
QClass_t qclass;
};
} // namespace dns
} // namespace llarp
#endif

@ -0,0 +1,47 @@
#ifndef LLARP_DNS_RR_HPP
#define LLARP_DNS_RR_HPP
#include <llarp/dns/name.hpp>
#include <llarp/dns/serialize.hpp>
#include <llarp/net_int.hpp>
#include <vector>
#include <memory>
namespace llarp
{
namespace dns
{
using RRClass_t = uint16_t;
using RRType_t = uint16_t;
using RR_RData_t = std::vector< byte_t >;
using RR_TTL_t = uint32_t;
struct ResourceRecord : public Serialize
{
ResourceRecord() = default;
ResourceRecord(const ResourceRecord& other);
ResourceRecord(ResourceRecord&& other);
bool
Encode(llarp_buffer_t* buf) const override;
bool
Decode(llarp_buffer_t* buf) override;
friend std::ostream&
operator<<(std::ostream& out, const ResourceRecord& rr)
{
return out << "[RR name=" << rr.rr_name << " type=" << rr.rr_type
<< " class=" << rr.rr_class << " ttl=" << rr.ttl
<< " rdata=[" << rr.rData.size() << " bytes]";
}
Name_t rr_name;
RRType_t rr_type;
RRClass_t rr_class;
RR_TTL_t ttl;
RR_RData_t rData;
};
} // namespace dns
} // namespace llarp
#endif

@ -0,0 +1,33 @@
#ifndef LLARP_DNS_SERIALIZE_HPP
#define LLARP_DNS_SERIALIZE_HPP
#include <llarp/buffer.h>
#include <vector>
namespace llarp
{
namespace dns
{
/// base type for serializable dns entities
struct Serialize
{
virtual ~Serialize() = default;
/// encode entity to buffer
virtual bool
Encode(llarp_buffer_t* buf) const = 0;
/// decode entity from buffer
virtual bool
Decode(llarp_buffer_t* buf) = 0;
};
bool
EncodeRData(llarp_buffer_t* buf, const std::vector< byte_t >& rdata);
bool
DecodeRData(llarp_buffer_t* buf, std::vector< byte_t >& rdata);
} // namespace dns
} // namespace llarp
#endif

@ -0,0 +1,101 @@
#ifndef LLARP_DNS_SERVER_HPP
#define LLARP_DNS_SERVER_HPP
#include <llarp/string_view.hpp>
#include <llarp/dns/message.hpp>
#include <llarp/ev.h>
#include <llarp/net.hpp>
#include <unordered_map>
namespace llarp
{
namespace dns
{
/// handler of dns query hooking
struct IQueryHandler
{
/// return true if we should hook this message
virtual bool
ShouldHookDNSMessage(const Message& msg) const = 0;
/// handle a hooked message
virtual bool
HandleHookedDNSMessage(Message query,
std::function< void(Message) > sendReply) = 0;
};
struct Proxy
{
Proxy(llarp_ev_loop* loop, IQueryHandler* handler);
bool
Start(const llarp::Addr& addr,
const std::vector< llarp::Addr >& resolvers);
void
Stop();
private:
/// low level packet handler
static void
HandleUDPRecv_client(llarp_udp_io*, const struct sockaddr*,
llarp_buffer_t);
static void
HandleUDPRecv_server(llarp_udp_io*, const struct sockaddr*,
llarp_buffer_t);
/// low level ticker
static void
HandleTick(llarp_udp_io*);
void
Tick(llarp_time_t now);
void
HandlePktClient(llarp::Addr from, llarp_buffer_t* buf);
void
HandlePktServer(llarp::Addr from, llarp_buffer_t* buf);
void
SendMessageTo(llarp::Addr to, Message msg);
llarp::Addr
PickRandomResolver() const;
private:
llarp_udp_io m_Server;
llarp_udp_io m_Client;
llarp_ev_loop* m_Loop;
IQueryHandler* m_QueryHandler;
std::vector< llarp::Addr > m_Resolvers;
struct TX
{
MsgID_t txid;
llarp::Addr from;
bool
operator==(const TX& other) const
{
return txid == other.txid && from == other.from;
}
struct Hash
{
size_t
operator()(const TX& t) const noexcept
{
return t.txid ^ llarp::Addr::Hash()(t.from);
}
};
};
// maps tx to who to send reply to
std::unordered_map< TX, llarp::Addr, TX::Hash > m_Forwarded;
};
} // namespace dns
} // namespace llarp
#endif

@ -0,0 +1,23 @@
#ifndef LLARP_DNS_STRING_HPP
#define LLARP_DNS_STRING_HPP
#include <string>
namespace llarp
{
namespace dns
{
using name_t = std::string;
/// decode name from buffer
bool
decode_name(llarp_buffer_t* buf, name_t& name);
/// encode name to buffer
bool
encode_name(llarp_buffer_t* buf, const name_t& name);
} // namespace dns
} // namespace llarp
#endif

@ -5,9 +5,8 @@
#include <llarp/ip.hpp>
#include <llarp/service/endpoint.hpp>
#include <llarp/threading.hpp>
#include <llarp/dnsd.hpp> // for relay
#include <llarp/dns_dotlokilookup.hpp> // for lookup
#include <llarp/dns_iptracker.hpp> // for tracker
#include <llarp/dns/server.hpp>
#include <llarp/net.hpp>
namespace llarp
{
@ -18,7 +17,7 @@ namespace llarp
static const char DefaultTunDstAddr[] = "10.10.0.1";
static const char DefaultTunSrcAddr[] = "10.10.0.2";
struct TunEndpoint : public service::Endpoint
struct TunEndpoint : public service::Endpoint, public dns::IQueryHandler
{
TunEndpoint(const std::string& nickname, llarp_router* r);
~TunEndpoint();
@ -29,6 +28,14 @@ namespace llarp
virtual void
Tick(llarp_time_t now) override;
bool
ShouldHookDNSMessage(const dns::Message& msg) const override;
bool
HandleHookedDNSMessage(
dns::Message query,
std::function< void(dns::Message) > sendreply) override;
void
TickTun(llarp_time_t now);
@ -66,16 +73,6 @@ namespace llarp
bool
HasLocalIP(const huint32_t& ip) const;
#ifndef WIN32
/// overrides Endpoint
bool
IsolationFailed() override
{
m_TunSetupResult.set_value(false);
return false;
}
#endif
llarp_tun_io tunif;
std::unique_ptr< llarp_fd_promise > Promise;
@ -173,18 +170,18 @@ namespace llarp
});
}
void
SendDNSReply(service::Address addr,
service::Endpoint::OutboundContext* ctx, dns::Message query,
std::function< void(dns::Message) > reply);
#ifndef WIN32
/// handles setup, given value true on success and false on failure to set
/// up interface
std::promise< bool > m_TunSetupResult;
/// handles fd injection force android
std::promise< int > m_VPNPromise;
#endif
/// DNS server per tun
struct dnsd_context dnsd;
/// DNS loki lookup subsystem configuration (also holds optional iptracker
/// for netns)
struct dotLokiLookup dll;
/// our dns resolver
dns::Proxy m_Resolver;
/// maps ip address to timestamp last active
std::unordered_map< huint32_t, llarp_time_t, huint32_t::Hash >
@ -195,8 +192,10 @@ namespace llarp
huint32_t m_NextIP;
/// highest ip address to allocate (host byte order)
huint32_t m_MaxIP;
/// upstream dns
llarp::Addr m_UpstreamDNSAddr;
/// our ip range we are using
llarp::IPRange m_OurRange;
/// upstream dns resolver list
std::vector< llarp::Addr > m_UpstreamResolvers;
/// local dns
llarp::Addr m_LocalResolverAddr;
};

@ -3,10 +3,10 @@
#include <llarp/address_info.hpp>
#include <llarp/net.h>
#include <functional>
#include <iostream>
#include "logger.hpp"
#include "mem.hpp"
#include <llarp/string_view.hpp>
#include <llarp/net_int.hpp>
#include <vector>
#include <stdlib.h> // for itoa
@ -55,183 +55,6 @@ llarp_getPrivateIfs();
namespace llarp
{
// clang-format off
struct huint32_t
{
uint32_t h;
constexpr huint32_t
operator &(huint32_t x) const { return huint32_t{uint32_t(h & x.h)}; }
constexpr huint32_t
operator |(huint32_t x) const { return huint32_t{uint32_t(h | x.h)}; }
constexpr huint32_t
operator ^(huint32_t x) const { return huint32_t{uint32_t(h ^ x.h)}; }
constexpr huint32_t
operator ~() const { return huint32_t{uint32_t(~h)}; }
inline huint32_t operator ++() { ++h; return *this; }
inline huint32_t operator --() { --h; return *this; }
constexpr bool operator <(huint32_t x) const { return h < x.h; }
constexpr bool operator ==(huint32_t x) const { return h == x.h; }
friend std::ostream&
operator<<(std::ostream& out, const huint32_t& a)
{
uint32_t n = htonl(a.h);
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp)))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
operator ()(huint32_t x) const
{
return std::hash< uint32_t >{}(x.h);
}
};
};
struct nuint32_t
{
uint32_t n;
constexpr nuint32_t
operator &(nuint32_t x) const { return nuint32_t{uint32_t(n & x.n)}; }
constexpr nuint32_t
operator |(nuint32_t x) const { return nuint32_t{uint32_t(n | x.n)}; }
constexpr nuint32_t
operator ^(nuint32_t x) const { return nuint32_t{uint32_t(n ^ x.n)}; }
constexpr nuint32_t
operator ~() const { return nuint32_t{uint32_t(~n)}; }
inline nuint32_t operator ++() { ++n; return *this; }
inline nuint32_t operator --() { --n; return *this; }
constexpr bool operator <(nuint32_t x) const { return n < x.n; }
constexpr bool operator ==(nuint32_t x) const { return n == x.n; }
friend std::ostream&
operator<<(std::ostream& out, const nuint32_t& a)
{
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&a.n, tmp, sizeof(tmp)))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
operator ()(nuint32_t x) const
{
return std::hash< uint32_t >{}(x.n);
}
};
};
struct huint16_t
{
uint16_t h;
constexpr huint16_t
operator &(huint16_t x) const { return huint16_t{uint16_t(h & x.h)}; }
constexpr huint16_t
operator |(huint16_t x) const { return huint16_t{uint16_t(h | x.h)}; }
constexpr huint16_t
operator ~() const { return huint16_t{uint16_t(~h)}; }
inline huint16_t operator ++() { ++h; return *this; }
inline huint16_t operator --() { --h; return *this; }
constexpr bool operator <(huint16_t x) const { return h < x.h; }
constexpr bool operator ==(huint16_t x) const { return h == x.h; }
friend std::ostream&
operator<<(std::ostream& out, const huint16_t& a)
{
return out << a.h;
}
struct Hash
{
inline size_t
operator ()(huint16_t x) const
{
return std::hash< uint16_t >{}(x.h);
}
};
};
struct nuint16_t
{
uint16_t n;
constexpr nuint16_t
operator &(nuint16_t x) const { return nuint16_t{uint16_t(n & x.n)}; }
constexpr nuint16_t
operator |(nuint16_t x) const { return nuint16_t{uint16_t(n | x.n)}; }
constexpr nuint16_t
operator ~() const { return nuint16_t{uint16_t(~n)}; }
inline nuint16_t operator ++() { ++n; return *this; }
inline nuint16_t operator --() { --n; return *this; }
constexpr bool operator <(nuint16_t x) const { return n < x.n; }
constexpr bool operator ==(nuint16_t x) const { return n == x.n; }
friend std::ostream&
operator<<(std::ostream& out, const nuint16_t& a)
{
return out << ntohs(a.n);
}
struct Hash
{
inline size_t
operator ()(nuint16_t x) const
{
return std::hash< uint16_t >{}(x.n);
}
};
};
// clang-format on
static inline nuint32_t
xhtonl(huint32_t x)
{
return nuint32_t{htonl(x.h)};
}
static inline huint32_t
xntohl(nuint32_t x)
{
return huint32_t{ntohl(x.n)};
}
static inline nuint16_t
xhtons(huint16_t x)
{
return nuint16_t{htons(x.h)};
}
static inline huint16_t
xntohs(nuint16_t x)
{
return huint16_t{ntohs(x.n)};
}
struct IPRange
{
huint32_t addr;

@ -0,0 +1,199 @@
#ifndef LLARP_NET_INT_HPP
#define LLARP_NET_INT_HPP
// for addrinfo
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#define inet_aton(x, y) inet_pton(AF_INET, x, y)
#endif
#include <stdlib.h> // for itoa
#include <iostream>
#include <llarp/net.h>
namespace llarp
{
// clang-format off
struct huint32_t
{
uint32_t h;
constexpr huint32_t
operator &(huint32_t x) const { return huint32_t{uint32_t(h & x.h)}; }
constexpr huint32_t
operator |(huint32_t x) const { return huint32_t{uint32_t(h | x.h)}; }
constexpr huint32_t
operator ^(huint32_t x) const { return huint32_t{uint32_t(h ^ x.h)}; }
constexpr huint32_t
operator ~() const { return huint32_t{uint32_t(~h)}; }
inline huint32_t operator ++() { ++h; return *this; }
inline huint32_t operator --() { --h; return *this; }
constexpr bool operator <(huint32_t x) const { return h < x.h; }
constexpr bool operator ==(huint32_t x) const { return h == x.h; }
friend std::ostream&
operator<<(std::ostream& out, const huint32_t& a)
{
uint32_t n = htonl(a.h);
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp)))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
operator ()(huint32_t x) const
{
return std::hash< uint32_t >{}(x.h);
}
};
};
struct nuint32_t
{
uint32_t n;
constexpr nuint32_t
operator &(nuint32_t x) const { return nuint32_t{uint32_t(n & x.n)}; }
constexpr nuint32_t
operator |(nuint32_t x) const { return nuint32_t{uint32_t(n | x.n)}; }
constexpr nuint32_t
operator ^(nuint32_t x) const { return nuint32_t{uint32_t(n ^ x.n)}; }
constexpr nuint32_t
operator ~() const { return nuint32_t{uint32_t(~n)}; }
inline nuint32_t operator ++() { ++n; return *this; }
inline nuint32_t operator --() { --n; return *this; }
constexpr bool operator <(nuint32_t x) const { return n < x.n; }
constexpr bool operator ==(nuint32_t x) const { return n == x.n; }
friend std::ostream&
operator<<(std::ostream& out, const nuint32_t& a)
{
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&a.n, tmp, sizeof(tmp)))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
operator ()(nuint32_t x) const
{
return std::hash< uint32_t >{}(x.n);
}
};
};
struct huint16_t
{
uint16_t h;
constexpr huint16_t
operator &(huint16_t x) const { return huint16_t{uint16_t(h & x.h)}; }
constexpr huint16_t
operator |(huint16_t x) const { return huint16_t{uint16_t(h | x.h)}; }
constexpr huint16_t
operator ~() const { return huint16_t{uint16_t(~h)}; }
inline huint16_t operator ++() { ++h; return *this; }
inline huint16_t operator --() { --h; return *this; }
constexpr bool operator <(huint16_t x) const { return h < x.h; }
constexpr bool operator ==(huint16_t x) const { return h == x.h; }
friend std::ostream&
operator<<(std::ostream& out, const huint16_t& a)
{
return out << a.h;
}
struct Hash
{
inline size_t
operator ()(huint16_t x) const
{
return std::hash< uint16_t >{}(x.h);
}
};
};
struct nuint16_t
{
uint16_t n;
constexpr nuint16_t
operator &(nuint16_t x) const { return nuint16_t{uint16_t(n & x.n)}; }
constexpr nuint16_t
operator |(nuint16_t x) const { return nuint16_t{uint16_t(n | x.n)}; }
constexpr nuint16_t
operator ~() const { return nuint16_t{uint16_t(~n)}; }
inline nuint16_t operator ++() { ++n; return *this; }
inline nuint16_t operator --() { --n; return *this; }
constexpr bool operator <(nuint16_t x) const { return n < x.n; }
constexpr bool operator ==(nuint16_t x) const { return n == x.n; }
friend std::ostream&
operator<<(std::ostream& out, const nuint16_t& a)
{
return out << ntohs(a.n);
}
struct Hash
{
inline size_t
operator ()(nuint16_t x) const
{
return std::hash< uint16_t >{}(x.n);
}
};
};
// clang-format on
static inline nuint32_t
xhtonl(huint32_t x)
{
return nuint32_t{htonl(x.h)};
}
static inline huint32_t
xntohl(nuint32_t x)
{
return huint32_t{ntohl(x.n)};
}
static inline nuint16_t
xhtons(huint16_t x)
{
return nuint16_t{htons(x.h)};
}
static inline huint16_t
xntohs(nuint16_t x)
{
return huint16_t{ntohs(x.n)};
}
} // namespace llarp
#endif

@ -190,8 +190,8 @@ namespace llarp
return *i.first.data_l() ^ *i.second.data_l();
}
};
using Mtx_t = llarp::util::Mutex;
using Lock_t = llarp::util::Lock;
using Mtx_t = llarp::util::NullMutex;
using Lock_t = llarp::util::NullLock;
using PathMap_t = std::unordered_map< PathInfo_t, Path*, PathInfoHash >;
mutable Mtx_t m_PathsMutex;
PathMap_t m_Paths;

@ -9,14 +9,14 @@ namespace llarp
{
namespace service
{
/// Snapp Address
/// Snapp/Snode Address
struct Address
{
std::string
ToString() const;
ToString(const char* tld = ".loki") const;
bool
FromString(const std::string& str);
FromString(const std::string& str, const char* tld = ".loki");
Address()
{

@ -117,13 +117,3 @@ llarp_buffer_read_uint32(llarp_buffer_t* buf, uint32_t* i)
buf->cur += sizeof(uint32_t);
return true;
}
bool
llarp_buffer_put_uint32(llarp_buffer_t* buf, uint32_t* i)
{
if(llarp_buffer_size_left(*buf) < sizeof(uint32_t))
return false;
*i = bufbe32toh(buf->cur);
buf->cur += sizeof(uint32_t);
return true;
}

@ -37,6 +37,7 @@ namespace llarp
system = find_section(top, "system", section_t{});
api = find_section(top, "api", section_t{});
lokid = find_section(top, "lokid", section_t{});
bootstrap = find_section(top, "bootstrap", section_t{});
return true;
}
return false;

@ -341,8 +341,10 @@ extern "C"
llarp_main_init_dotLokiLookup(struct llarp_main *ptr,
struct dotLokiLookup *dll)
{
dll->logic = ptr->ctx->logic;
return true;
(void)ptr;
(void)dll;
// TODO: gutt me
return false;
}
void

@ -0,0 +1,211 @@
#include <llarp/dns/message.hpp>
#include <llarp/endian.hpp>
#include <llarp/logger.hpp>
#include <llarp/buffer.hpp>
namespace llarp
{
namespace dns
{
bool
MessageHeader::Encode(llarp_buffer_t* buf) const
{
if(!llarp_buffer_put_uint16(buf, id))
return false;
if(!llarp_buffer_put_uint16(buf, fields))
return false;
if(!llarp_buffer_put_uint16(buf, qd_count))
return false;
if(!llarp_buffer_put_uint16(buf, an_count))
return false;
if(!llarp_buffer_put_uint16(buf, ns_count))
return false;
return llarp_buffer_put_uint16(buf, ar_count);
}
bool
MessageHeader::Decode(llarp_buffer_t* buf)
{
if(!llarp_buffer_read_uint16(buf, &id))
return false;
if(!llarp_buffer_read_uint16(buf, &fields))
return false;
if(!llarp_buffer_read_uint16(buf, &qd_count))
return false;
if(!llarp_buffer_read_uint16(buf, &an_count))
return false;
if(!llarp_buffer_read_uint16(buf, &ns_count))
return false;
return llarp_buffer_read_uint16(buf, &ar_count);
}
Message::Message(Message&& other)
: hdr_id(std::move(other.hdr_id))
, hdr_fields(std::move(other.hdr_fields))
, questions(std::move(other.questions))
, answers(std::move(other.answers))
, authorities(std::move(other.authorities))
, additional(std::move(other.additional))
{
}
Message::Message(const Message& other)
: hdr_id(other.hdr_id)
, hdr_fields(other.hdr_fields)
, questions(other.questions)
, answers(other.answers)
, authorities(other.authorities)
, additional(other.additional)
{
}
Message::Message(const MessageHeader& hdr)
: hdr_id(hdr.id)
, hdr_fields(hdr.fields)
, questions(size_t(hdr.qd_count))
, answers(size_t(hdr.an_count))
, authorities(size_t(hdr.ns_count))
, additional(size_t(hdr.ar_count))
{
}
bool
Message::Encode(llarp_buffer_t* buf) const
{
MessageHeader hdr;
hdr.id = hdr_id;
hdr.fields = hdr_fields;
hdr.qd_count = questions.size();
hdr.an_count = answers.size();
hdr.ns_count = authorities.size();
hdr.ar_count = additional.size();
if(!hdr.Encode(buf))
return false;
for(const auto& question : questions)
if(!question.Encode(buf))
return false;
for(const auto& answer : answers)
if(!answer.Encode(buf))
return false;
for(const auto& auth : authorities)
if(!auth.Encode(buf))
return false;
for(const auto& rr : additional)
if(!rr.Encode(buf))
return false;
return true;
}
bool
Message::Decode(llarp_buffer_t* buf)
{
for(auto& qd : questions)
{
if(!qd.Decode(buf))
{
llarp::LogError("failed to decode question");
return false;
}
llarp::LogDebug(qd);
}
for(auto& an : answers)
{
if(!an.Decode(buf))
{
llarp::LogError("failed to decode answer");
return false;
}
llarp::LogDebug(an);
}
for(auto& ns : authorities)
{
if(!ns.Decode(buf))
{
llarp::LogError("failed to decode authority");
return false;
}
llarp::LogDebug(ns);
}
for(auto& ar : additional)
{
if(!ar.Decode(buf))
{
llarp::LogError("failed to decode additonal");
return false;
}
llarp::LogDebug(ar);
}
return true;
}
void
Message::AddINReply(llarp::huint32_t ip)
{
if(questions.size())
{
hdr_fields |= (1 << 15);
const auto& question = questions[0];
ResourceRecord rec;
rec.rr_name = question.qname;
rec.rr_type = 1;
rec.rr_class = 1;
rec.ttl = 1;
rec.rData.resize(4);
htobe32buf(rec.rData.data(), ip.h);
answers.emplace_back(std::move(rec));
}
}
void
Message::AddAReply(std::string name)
{
if(questions.size())
{
hdr_fields |= (1 << 15);
const auto& question = questions[0];
answers.emplace_back();
auto& rec = answers.back();
rec.rr_name = question.qname;
rec.rr_type = question.qtype;
rec.rr_class = 1;
rec.ttl = 1;
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(EncodeName(&buf, name))
{
buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz);
memcpy(rec.rData.data(), buf.base, buf.sz);
}
}
}
void
Message::AddNXReply()
{
if(questions.size())
{
hdr_fields |= (1 << 15) | (1 << 3);
const auto& question = questions[0];
answers.emplace_back();
auto& nx = answers.back();
nx.rr_name = question.qname;
nx.rr_type = question.qtype;
nx.rr_class = question.qclass;
nx.ttl = 1;
nx.rData.resize(1);
nx.rData.data()[0] = 0;
}
}
} // namespace dns
} // namespace llarp

@ -0,0 +1,102 @@
#include <llarp/dns/name.hpp>
#include <llarp/net.hpp>
#include <sstream>
#include <algorithm>
namespace llarp
{
namespace dns
{
bool
DecodeName(llarp_buffer_t* buf, Name_t& name)
{
if(llarp_buffer_size_left(*buf) < 1)
return false;
std::stringstream ss;
size_t l;
do
{
l = *buf->cur;
buf->cur++;
if(l)
{
if(l > 63)
{
llarp::LogError("decode name failed, field too big: ", l, " > 63");
llarp::DumpBuffer(*buf);
return false;
}
if(llarp_buffer_size_left(*buf) < l)
return false;
ss << Name_t((const char*)buf->cur, l);
ss << ".";
}
buf->cur = buf->cur + l;
} while(l);
name = ss.str();
return true;
}
bool
EncodeName(llarp_buffer_t* buf, const Name_t& name)
{
std::stringstream ss;
if(name.size() && name[name.size() - 1] == '.')
ss << name.substr(0, name.size() - 1);
else
ss << name;
std::string part;
while(std::getline(ss, part, '.'))
{
size_t l = part.length();
if(l > 63)
return false;
*(buf->cur) = l;
buf->cur++;
if(llarp_buffer_size_left(*buf) < l)
return false;
if(l)
{
memcpy(buf->cur, part.data(), l);
buf->cur += l;
}
else
break;
}
*buf->cur = 0;
buf->cur++;
return true;
}
bool
DecodePTR(const Name_t& name, huint32_t& ip)
{
auto pos = name.find(".in-addr.arpa");
if(pos == std::string::npos)
return false;
std::string sub = name.substr(0, pos + 1);
if(std::count(sub.begin(), sub.end(), '.') == 4)
{
uint8_t a, b, c, d;
pos = sub.find('.');
d = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1);
pos = sub.find('.');
c = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1);
pos = sub.find('.');
b = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1);
pos = sub.find('.');
a = atoi(sub.substr(0, pos).c_str());
ip = llarp::ipaddr_ipv4_bits(a, b, c, d);
return true;
}
else
return false;
}
} // namespace dns
} // namespace llarp

@ -0,0 +1,50 @@
#include <llarp/dns/question.hpp>
#include <llarp/logger.hpp>
namespace llarp
{
namespace dns
{
Question::Question(Question&& other)
: qname(std::move(other.qname))
, qtype(std::move(other.qtype))
, qclass(std::move(other.qclass))
{
}
Question::Question(const Question& other)
: qname(other.qname), qtype(other.qtype), qclass(other.qclass)
{
}
bool
Question::Encode(llarp_buffer_t* buf) const
{
if(!EncodeName(buf, qname))
return false;
if(!llarp_buffer_put_uint16(buf, qtype))
return false;
return llarp_buffer_put_uint16(buf, qclass);
}
bool
Question::Decode(llarp_buffer_t* buf)
{
if(!DecodeName(buf, qname))
{
llarp::LogError("failed to decode name");
return false;
}
if(!llarp_buffer_read_uint16(buf, &qtype))
{
llarp::LogError("failed to decode type");
return false;
}
if(!llarp_buffer_read_uint16(buf, &qclass))
{
llarp::LogError("failed to decode class");
return false;
}
return true;
}
} // namespace dns
} // namespace llarp

@ -0,0 +1,83 @@
#include <llarp/dns/rr.hpp>
#include <llarp/logger.hpp>
namespace llarp
{
namespace dns
{
ResourceRecord::ResourceRecord(const ResourceRecord& other)
: rr_name(other.rr_name)
, rr_type(other.rr_type)
, rr_class(other.rr_class)
, ttl(other.ttl)
, rData(other.rData)
{
}
ResourceRecord::ResourceRecord(ResourceRecord&& other)
: rr_name(std::move(other.rr_name))
, rr_type(std::move(other.rr_type))
, rr_class(std::move(other.rr_class))
, ttl(std::move(other.ttl))
, rData(std::move(other.rData))
{
}
bool
ResourceRecord::Encode(llarp_buffer_t* buf) const
{
if(!EncodeName(buf, rr_name))
{
return false;
}
if(!llarp_buffer_put_uint16(buf, rr_type))
{
return false;
}
if(!llarp_buffer_put_uint16(buf, rr_class))
{
return false;
}
if(!llarp_buffer_put_uint32(buf, ttl))
{
return false;
}
if(!EncodeRData(buf, rData))
{
return false;
}
return true;
}
bool
ResourceRecord::Decode(llarp_buffer_t* buf)
{
if(!DecodeName(buf, rr_name))
{
llarp::LogError("failed to decode rr name");
return false;
}
if(!llarp_buffer_read_uint16(buf, &rr_type))
{
llarp::LogError("failed to decode rr type");
return false;
}
if(!llarp_buffer_read_uint16(buf, &rr_class))
{
llarp::LogError("failed to decode rr class");
return false;
}
if(!llarp_buffer_read_uint32(buf, &ttl))
{
llarp::LogError("failed to decode ttl");
return false;
}
if(!DecodeRData(buf, rData))
{
llarp::LogError("failed to decode rr rdata");
return false;
}
return true;
}
} // namespace dns
} // namespace llarp

@ -0,0 +1,42 @@
#include <llarp/dns/serialize.hpp>
#include <llarp/net_int.hpp>
namespace llarp
{
namespace dns
{
bool
EncodeRData(llarp_buffer_t* buf, const std::vector< byte_t >& v)
{
if(v.size() > 65536)
return false;
uint16_t len = v.size();
if(!llarp_buffer_put_uint16(buf, len))
return false;
if(llarp_buffer_size_left(*buf) < len)
return false;
memcpy(buf->cur, v.data(), len);
buf->cur += len;
return true;
}
bool
DecodeRData(llarp_buffer_t* buf, std::vector< byte_t >& v)
{
uint16_t len;
if(!llarp_buffer_read_uint16(buf, &len))
return false;
size_t left = llarp_buffer_size_left(*buf);
if(left < len)
return false;
v.resize(size_t(len));
if(len)
{
memcpy(v.data(), buf->cur, len);
buf->cur += len;
}
return true;
}
} // namespace dns
} // namespace llarp

@ -0,0 +1,158 @@
#include <llarp/dns/server.hpp>
namespace llarp
{
namespace dns
{
Proxy::Proxy(llarp_ev_loop* loop, IQueryHandler* h)
: m_Loop(loop), m_QueryHandler(h)
{
m_Client.user = this;
m_Server.user = this;
m_Client.tick = nullptr;
m_Server.tick = nullptr;
m_Client.recvfrom = &HandleUDPRecv_client;
m_Server.recvfrom = &HandleUDPRecv_server;
}
void
Proxy::Stop()
{
}
bool
Proxy::Start(const llarp::Addr& addr,
const std::vector< llarp::Addr >& resolvers)
{
m_Resolvers.clear();
m_Resolvers = resolvers;
if(m_Resolvers.size() == 0)
{
llarp::LogError("no upstream dns provide specified");
return false;
}
llarp::Addr any("0.0.0.0", 0);
return llarp_ev_add_udp(m_Loop, &m_Server, addr) == 0
&& llarp_ev_add_udp(m_Loop, &m_Client, any) == 0;
}
void
Proxy::HandleUDPRecv_server(llarp_udp_io* u, const sockaddr* from,
llarp_buffer_t buf)
{
static_cast< Proxy* >(u->user)->HandlePktServer(*from, &buf);
}
void
Proxy::HandleUDPRecv_client(llarp_udp_io* u, const sockaddr* from,
llarp_buffer_t buf)
{
static_cast< Proxy* >(u->user)->HandlePktClient(*from, &buf);
}
llarp::Addr
Proxy::PickRandomResolver() const
{
size_t sz = m_Resolvers.size();
if(sz == 0)
return llarp::Addr("1.1.1.1", 53);
if(sz == 1)
return m_Resolvers[0];
auto itr = m_Resolvers.begin();
std::advance(itr, llarp_randint() % sz);
return *itr;
}
void
Proxy::HandleTick(llarp_udp_io*)
{
}
void
Proxy::SendMessageTo(llarp::Addr to, Message msg)
{
byte_t tmp[1500] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(msg.Encode(&buf))
{
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
llarp_ev_udp_sendto(&m_Server, to, buf);
}
else
llarp::LogWarn("failed to encode dns message when sending");
}
void
Proxy::HandlePktClient(llarp::Addr from, llarp_buffer_t* pkt)
{
MessageHeader hdr;
if(!hdr.Decode(pkt))
{
llarp::LogWarn("failed to parse dns header from ", from);
return;
}
TX tx = {hdr.id, from};
auto itr = m_Forwarded.find(tx);
if(itr != m_Forwarded.end())
{
llarp_buffer_t buf;
buf.sz = pkt->sz;
buf.base = pkt->base;
buf.cur = buf.base;
// forward reply
llarp_ev_udp_sendto(&m_Server, itr->second, buf);
// remove pending
m_Forwarded.erase(itr);
}
}
void
Proxy::HandlePktServer(llarp::Addr from, llarp_buffer_t* pkt)
{
MessageHeader hdr;
if(!hdr.Decode(pkt))
{
llarp::LogWarn("failed to parse dns header from ", from);
return;
}
TX tx = {hdr.id, from};
auto itr = m_Forwarded.find(tx);
Message msg(hdr);
if(!msg.Decode(pkt))
{
llarp::LogWarn("failed to parse dns message from ", from);
return;
}
if(m_QueryHandler && m_QueryHandler->ShouldHookDNSMessage(msg))
{
if(!m_QueryHandler->HandleHookedDNSMessage(
std::move(msg),
std::bind(&Proxy::SendMessageTo, this, from,
std::placeholders::_1)))
{
llarp::LogWarn("failed to handle hooked dns");
}
return;
}
else if(itr == m_Forwarded.end())
{
// new forwarded query
tx.from = PickRandomResolver();
m_Forwarded[tx] = from;
llarp_buffer_t buf;
buf.sz = pkt->sz;
buf.base = pkt->base;
buf.cur = buf.base;
// do query
llarp_ev_udp_sendto(&m_Client, tx.from, buf);
}
else
{
// drop (?)
}
}
} // namespace dns
} // namespace llarp

@ -24,6 +24,7 @@ namespace llarp
: service::Endpoint(nickname, r)
, m_UserToNetworkPktQueue(nickname + "_sendq", r->netloop, r->netloop)
, m_NetworkToUserPktQueue(nickname + "_recvq", r->netloop, r->netloop)
, m_Resolver(r->netloop, this)
{
#ifdef ANDROID
tunif.get_fd_promise = &get_tun_fd_promise;
@ -40,12 +41,9 @@ namespace llarp
strncpy(tunif.ifaddr, DefaultTunSrcAddr, sizeof(tunif.ifaddr) - 1);
strncpy(tunif.ifname, DefaultTunIfname, sizeof(tunif.ifname) - 1);
#endif
tunif.tick = nullptr;
tunif.before_write = &tunifBeforeWrite;
tunif.recvpkt = &tunifRecvPkt;
this->dll.ip_tracker = nullptr;
this->dll.user = &r->hiddenServiceContext;
// this->dll.callback = std::bind(&TunEndpoint::MapAddress, this);
tunif.tick = nullptr;
tunif.before_write = &tunifBeforeWrite;
tunif.recvpkt = &tunifRecvPkt;
}
bool
@ -89,8 +87,9 @@ namespace llarp
resolverAddr = v.substr(0, pos);
dnsport = std::atoi(v.substr(pos + 1).c_str());
}
m_UpstreamDNSAddr = llarp::Addr(resolverAddr, dnsport);
llarp::LogInfo(Name(), " upstream dns set to ", m_UpstreamDNSAddr);
m_UpstreamResolvers.emplace_back(resolverAddr, dnsport);
llarp::LogInfo(Name(), "adding upstream dns set to ", resolverAddr, ":",
dnsport);
}
if(k == "mapaddr")
{
@ -156,15 +155,6 @@ namespace llarp
llarp::LogInfo(Name() + " set ifaddr to ", addr, " with netmask ",
tunif.netmask);
strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1);
// set up address in dotLokiLookup
// llarp::Addr tunIp(tunif.ifaddr);
llarp::huint32_t tunIpV4;
tunIpV4.h = inet_addr(tunif.ifaddr);
// related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
dns_iptracker_setup(
this->dll.ip_tracker,
tunIpV4); // claim GW IP to make sure it's not inuse
return true;
}
return Endpoint::SetOption(k, v);
@ -184,6 +174,116 @@ namespace llarp
std::move(pkt));
}
bool
TunEndpoint::HandleHookedDNSMessage(
dns::Message msg, std::function< void(dns::Message) > reply)
{
if(msg.questions.size() != 1)
{
llarp::LogWarn("bad number of dns questions: ", msg.questions.size());
return false;
}
std::string qname = msg.questions[0].qname;
if(msg.questions[0].qtype == 1)
{
// forward dns
llarp::service::Address addr;
if(addr.FromString(qname, ".loki"))
{
return EnsurePathToService(
addr,
std::bind(&TunEndpoint::SendDNSReply, this, std::placeholders::_1,
std::placeholders::_2, msg, reply),
2000);
}
else if(addr.FromString(qname, ".snode"))
{
// TODO: add hook to EnsurePathToSNode
EnsurePathToSNode(addr.data());
huint32_t ip = ObtainIPForAddr(addr.data(), true);
msg.AddINReply(ip);
}
else
msg.AddNXReply();
reply(msg);
}
else if(msg.questions[0].qtype == 12)
{
// reverse dns
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
{
msg.AddNXReply();
reply(msg);
return true;
}
llarp::service::Address addr =
ObtainAddrForIP< llarp::service::Address >(ip, true);
if(!addr.IsZero())
{
msg.AddAReply(addr.ToString(".snode"));
reply(msg);
return true;
}
addr = ObtainAddrForIP< llarp::service::Address >(ip, false);
if(!addr.IsZero())
{
msg.AddAReply(addr.ToString(".loki"));
reply(msg);
return true;
}
msg.AddNXReply();
reply(msg);
return true;
}
else
{
msg.AddNXReply();
reply(msg);
}
return true;
}
bool
TunEndpoint::ShouldHookDNSMessage(const dns::Message &msg) const
{
llarp::service::Address addr;
if(msg.questions.size() == 1)
{
if(addr.FromString(msg.questions[0].qname, ".loki"))
return true;
if(addr.FromString(msg.questions[0].qname, ".snode"))
return true;
if(msg.questions[0].qtype == 12)
{
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
return false;
return m_OurRange.Contains(ip);
}
}
return false;
}
void
TunEndpoint::SendDNSReply(service::Address addr,
service::Endpoint::OutboundContext *ctx,
dns::Message request,
std::function< void(dns::Message) > reply)
{
if(ctx)
{
huint32_t ip = ObtainIPForAddr(addr.data(), false);
request.AddINReply(ip);
}
else
request.AddNXReply();
reply(request);
}
bool
TunEndpoint::MapAddress(const service::Address &addr, huint32_t ip,
bool SNode)
@ -208,44 +308,9 @@ namespace llarp
bool
TunEndpoint::Start()
{
// do network isolation first
if(!Endpoint::Start())
return false;
#ifdef WIN32
return SetupNetworking();
#else
if(!NetworkIsIsolated())
{
llarp::LogInfo("Setting up global DNS IP tracker");
llarp::huint32_t tunIpV4;
tunIpV4.h = inet_addr(tunif.ifaddr);
dns_iptracker_setup_dotLokiLookup(
&this->dll, tunIpV4); // just set ups dll to use global iptracker
dns_iptracker_setup(
this->dll.ip_tracker,
tunIpV4); // claim GW IP to make sure it's not inuse
// set up networking in currrent thread if we are not isolated
if(!SetupNetworking())
return false;
}
else
{
llarp::LogInfo("Setting up per netns DNS IP tracker");
llarp::huint32_t tunIpV4;
tunIpV4.h = inet_addr(tunif.ifaddr);
llarp::Addr tunIp(tunif.ifaddr);
this->dll.ip_tracker = new dns_iptracker;
dns_iptracker_setup_dotLokiLookup(
&this->dll, tunIpV4); // just set ups dll to use global iptracker
dns_iptracker_setup(
this->dll.ip_tracker,
tunIpV4); // claim GW IP to make sure it's not inuse
}
// wait for result for network setup
llarp::LogInfo("waiting for tun interface...");
return m_TunSetupResult.get_future().get();
#endif
}
bool
@ -288,8 +353,8 @@ namespace llarp
int s = inet_pton(res->ai_family, tunif.ifaddr, buf);
if (s <= 0)
{
llarp::LogError(Name(), " failed to set up tun interface, cant parse ",
tunif.ifaddr); return false;
llarp::LogError(Name(), " failed to set up tun interface, cant parse
", tunif.ifaddr); return false;
}
*/
if(res->ai_family == AF_INET6)
@ -311,13 +376,14 @@ namespace llarp
llarp::Addr lAddr(tunif.ifaddr);
m_OurIP = lAddr.xtohl();
m_NextIP = m_OurIP;
auto xmask = netmask_ipv4_bits(tunif.netmask);
m_MaxIP = m_OurIP ^ (~xmask);
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);
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP);
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ",
m_OurRange);
MapAddress(m_Identity.pub.Addr(), m_OurIP, IsSNode());
return true;
}
@ -326,37 +392,17 @@ namespace llarp
TunEndpoint::SetupNetworking()
{
llarp::LogInfo("Set Up networking for ", Name());
bool result = SetupTun();
#ifndef WIN32
m_TunSetupResult.set_value(
result); // now that NT has tun, we don't need the CPP guard
#endif
if(!NetworkIsIsolated())
if(!SetupTun())
{
// need to check to see if we have more than one hidden service
// well we'll only use the primary
// FIXME: detect number of hidden services
llarp::LogWarn(
"Only utilizing first hidden service for .loki look ups");
// because we can't find to the tun interface because we don't want it
// accessible on lokinet we can only bind one to loopback, and we can't
// really utilize anything other than port 53 we can't bind to our
// public interface, don't want it exploitable maybe we could detect if
// you have a private interface
llarp::LogError(Name(), " failed to set up network interface");
return false;
}
llarp::LogInfo("TunDNS set up ", m_LocalResolverAddr, " to ",
m_UpstreamDNSAddr);
if(!llarp_dnsd_init(&this->dnsd, EndpointLogic(), EndpointNetLoop(),
m_LocalResolverAddr, m_UpstreamDNSAddr))
if(!m_Resolver.Start(m_LocalResolverAddr, m_UpstreamResolvers))
{
llarp::LogError("Couldnt init dns daemon");
llarp::LogError(Name(), " failed to start dns server");
return false;
}
// configure hook for .loki lookup
dnsd.intercept = &llarp_dotlokilookup_handler;
// set dotLokiLookup (this->dll) configuration
dnsd.user = &this->dll;
return result;
return true;
}
void
@ -580,8 +626,6 @@ namespace llarp
return pkt.Load(buf) && pkt.Header()->version == 4;
}))
{
llarp::LogInfo("Failed to parse ipv4 packet");
llarp::DumpBuffer(buf);
}
}

@ -20,6 +20,7 @@ namespace llarp
Handler result;
size_t idx = 0;
llarp_router* router = nullptr;
llarp_threadpool* worker = nullptr;
llarp_logic* logic = nullptr;
llarp_crypto* crypto = nullptr;
@ -136,24 +137,18 @@ namespace llarp
void
pathbuilder_generated_keys(AsyncPathKeyExchangeContext< path::Builder >* ctx)
{
RouterID remote = ctx->path->Upstream();
auto router = ctx->user->router;
if(!router)
{
llarp::LogError("null router");
return;
}
RouterID remote = ctx->path->Upstream();
const ILinkMessage* msg = &ctx->LRCM;
if(!router->SendToOrQueue(remote, msg))
if(!ctx->router->SendToOrQueue(remote, msg))
{
llarp::LogError("failed to send LRCM");
return;
}
// persist session with router until this path is done
router->PersistSessionUntil(remote, ctx->path->ExpireTime());
ctx->router->PersistSessionUntil(remote, ctx->path->ExpireTime());
// add own path
router->paths.AddOwnPath(ctx->pathset, ctx->path);
ctx->router->paths.AddOwnPath(ctx->pathset, ctx->path);
}
namespace path
@ -257,6 +252,7 @@ namespace llarp
// async generate keys
AsyncPathKeyExchangeContext< Builder >* ctx =
new AsyncPathKeyExchangeContext< Builder >(&router->crypto);
ctx->router = router;
ctx->pathset = this;
auto path = new llarp::path::Path(hops, this, roles);
path->SetBuildResultHook(std::bind(&llarp::path::Builder::HandlePathBuilt,

@ -530,6 +530,7 @@ llarp_router::Tick()
{
// llarp::LogDebug("tick router");
auto now = llarp_ev_loop_time_now_ms(netloop);
paths.TickPaths(now);
paths.ExpirePaths(now);
{
auto itr = m_PersistingSessions.begin();
@ -584,7 +585,6 @@ llarp_router::Tick()
{
ConnectToRandomRouters(minConnectedRouters);
}
paths.TickPaths(now);
exitContext.Tick(now);
if(rpcCaller)
rpcCaller->Tick(now);
@ -858,6 +858,7 @@ llarp_router::Run()
if(!SaveRC())
{
llarp::LogError("failed to save RC");
return false;
}
@ -1177,6 +1178,7 @@ namespace llarp
router_iter_config(llarp_config_iterator *iter, const char *section,
const char *key, const char *val)
{
llarp::LogDebug(section, " ", key, "=", val);
llarp_router *self = static_cast< llarp_router * >(iter->user);
int af;

@ -6,17 +6,17 @@ namespace llarp
namespace service
{
std::string
Address::ToString() const
Address::ToString(const char* tld) const
{
char tmp[(1 + 32) * 2] = {0};
std::string str = Base32Encode(*this, tmp);
return str + ".loki";
return str + tld;
}
bool
Address::FromString(const std::string& str)
Address::FromString(const std::string& str, const char* tld)
{
auto pos = str.find(".loki");
auto pos = str.find(tld);
if(pos == std::string::npos)
return false;
auto sub = str.substr(0, pos);

@ -43,8 +43,6 @@ struct llarpDNSdTest : public ::testing::Test
test_request.question.qClass = 1;
g_result = ""; // reset test global
g_length = 0;
llarp::SetLogLevel(
llarp::eLogNone); // turn off logging to keep gtest output pretty
}
};

@ -0,0 +1,147 @@
#include <llarp/dns/dns.hpp>
#include <gtest/gtest.h>
#include <algorithm>
#include <llarp/net.hpp>
struct DNSLibTest : public ::testing::Test
{
byte_t mem[1500];
llarp_buffer_t buf = llarp::StackBuffer< decltype(mem) >(mem);
void
SetUp()
{
buf.sz = sizeof(mem);
Rewind();
memset(mem, '$', sizeof(mem));
}
void
Rewind()
{
buf.cur = buf.base;
}
};
TEST_F(DNSLibTest, TestPTR)
{
llarp::huint32_t ip = {0};
llarp::huint32_t expected = llarp::ipaddr_ipv4_bits(10, 10, 10, 1);
ASSERT_TRUE(llarp::dns::DecodePTR("1.10.10.10.in-addr.arpa.", ip));
ASSERT_EQ(ip, expected);
};
TEST_F(DNSLibTest, TestSerializeHeader)
{
llarp::dns::MessageHeader hdr, other;
hdr.id = 0x1234;
hdr.fields = (1 << 15);
hdr.qd_count = 1;
hdr.an_count = 1;
hdr.ns_count = 0;
hdr.ar_count = 0;
ASSERT_TRUE(hdr.Encode(&buf));
ASSERT_TRUE((buf.cur - buf.base) == llarp::dns::MessageHeader::Size);
Rewind();
ASSERT_TRUE(other.Decode(&buf));
ASSERT_TRUE(hdr == other);
ASSERT_TRUE(other.id == 0x1234);
ASSERT_TRUE(other.fields == (1 << 15));
};
TEST_F(DNSLibTest, TestSerializeName)
{
const llarp::dns::Name_t name = "whatever.tld";
const llarp::dns::Name_t expected = "whatever.tld.";
llarp::dns::Name_t other;
Rewind();
ASSERT_TRUE(llarp::dns::EncodeName(&buf, name));
Rewind();
ASSERT_EQ(buf.base[0], 8);
ASSERT_EQ(buf.base[1], 'w');
ASSERT_EQ(buf.base[2], 'h');
ASSERT_EQ(buf.base[3], 'a');
ASSERT_EQ(buf.base[4], 't');
ASSERT_EQ(buf.base[5], 'e');
ASSERT_EQ(buf.base[6], 'v');
ASSERT_EQ(buf.base[7], 'e');
ASSERT_EQ(buf.base[8], 'r');
ASSERT_EQ(buf.base[9], 3);
ASSERT_EQ(buf.base[10], 't');
ASSERT_EQ(buf.base[11], 'l');
ASSERT_EQ(buf.base[12], 'd');
ASSERT_EQ(buf.base[13], 0);
ASSERT_TRUE(llarp::dns::DecodeName(&buf, other));
ASSERT_EQ(expected, other);
};
TEST_F(DNSLibTest, TestSerializeQuestion)
{
const std::string name = "whatever.tld";
const std::string expected_name = name + ".";
llarp::dns::Question q, other;
q.qname = name;
q.qclass = 1;
q.qtype = 1;
ASSERT_TRUE(q.Encode(&buf));
Rewind();
ASSERT_TRUE(other.Decode(&buf));
ASSERT_EQ(other.qname, expected_name);
ASSERT_EQ(q.qclass, other.qclass);
ASSERT_EQ(q.qtype, other.qtype);
};
TEST_F(DNSLibTest, TestSerializeMessage)
{
llarp::dns::Question expected_question;
expected_question.qname = "whatever.tld.";
expected_question.qclass = 1;
expected_question.qtype = 1;
llarp::dns::MessageHeader hdr, otherHdr;
hdr.id = 0xfeed;
hdr.fields = (1 << 15);
hdr.qd_count = 1;
hdr.an_count = 0;
hdr.ns_count = 0;
hdr.ar_count = 0;
llarp::dns::Message m(hdr);
m.hdr_id = 0x1234;
m.hdr_fields = (1 << 15);
auto& q = m.questions[0];
q.qname = "whatever.tld";
q.qclass = 1;
q.qtype = 1;
m.AddINReply({1});
ASSERT_EQ(m.questions.size(), 1U);
ASSERT_EQ(m.answers.size(), 1U);
ASSERT_TRUE(m.Encode(&buf));
Rewind();
ASSERT_TRUE(otherHdr.Decode(&buf));
llarp::dns::Message other(otherHdr);
ASSERT_TRUE(buf.cur - buf.base == llarp::dns::MessageHeader::Size);
ASSERT_TRUE(other.Decode(&buf));
ASSERT_EQ(other.questions.size(), 1U);
ASSERT_EQ(expected_question.qname, other.questions[0].qname);
ASSERT_EQ(expected_question.qclass, other.questions[0].qclass);
ASSERT_EQ(expected_question.qtype, other.questions[0].qtype);
ASSERT_TRUE(expected_question == other.questions[0]);
ASSERT_EQ(other.answers.size(), 1U);
ASSERT_EQ(other.answers[0].rData.size(), 4U);
};
TEST_F(DNSLibTest, TestEncodeDecode_RData)
{
static constexpr size_t rdatasize = 32;
llarp::dns::RR_RData_t rdata(rdatasize);
std::fill(rdata.begin(), rdata.end(), 'a');
llarp::dns::RR_RData_t other_rdata;
ASSERT_TRUE(llarp::dns::EncodeRData(&buf, rdata));
ASSERT_TRUE(buf.cur - buf.base == rdatasize + sizeof(uint16_t));
Rewind();
ASSERT_TRUE(llarp::dns::DecodeRData(&buf, other_rdata));
ASSERT_TRUE(rdata == other_rdata);
};
Loading…
Cancel
Save