1
1
Fork 0
mirror of https://github.com/oxen-io/lokinet synced 2023-12-14 06:53:00 +01:00

add dnslib unit test coverage

This commit is contained in:
Jeff Becker 2018-12-04 11:16:43 -05:00
parent 1d1bde2e88
commit 40678f9019
No known key found for this signature in database
GPG key ID: F357B3B42F6F9B05
17 changed files with 468 additions and 229 deletions

View file

@ -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

View file

@ -14,6 +14,10 @@ namespace llarp
struct MessageHeader : public Serialize
{
const static size_t Size = 12;
MessageHeader() = default;
MsgID_t id;
Fields_t fields;
Count_t qd_count;
@ -26,20 +30,33 @@ namespace llarp
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();
Message&
void
AddNXReply();
Message&
void
AddINReply(llarp::huint32_t addr);
Message&
void
AddAReply(std::string name);
bool
@ -48,7 +65,27 @@ namespace llarp
bool
Decode(llarp_buffer_t* buf) override;
MessageHeader hdr;
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;

View file

@ -8,17 +8,34 @@ namespace llarp
{
namespace dns
{
using QType_t = llarp::huint16_t;
using QClass_t = llarp::huint16_t;
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;

View file

@ -10,19 +10,31 @@ namespace llarp
{
namespace dns
{
using RRClass_t = llarp::huint16_t;
using RRType_t = llarp::huint16_t;
using RRClass_t = uint16_t;
using RRType_t = uint16_t;
using RR_RData_t = std::vector< byte_t >;
using RR_TTL_t = llarp::huint32_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;

View file

@ -19,14 +19,6 @@ namespace llarp
Decode(llarp_buffer_t* buf) = 0;
};
template < typename Int_t >
bool
EncodeInt(llarp_buffer_t* buf, const Int_t& i);
template < typename Int_t >
bool
DecodeInt(llarp_buffer_t* buf, Int_t& i);
bool
EncodeRData(llarp_buffer_t* buf, const std::vector< byte_t >& rdata);

View file

@ -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;
}

View file

@ -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;

View file

@ -1,5 +1,7 @@
#include <llarp/dns/message.hpp>
#include <llarp/endian.hpp>
#include <llarp/logger.hpp>
namespace llarp
{
namespace dns
@ -7,38 +9,76 @@ namespace llarp
bool
MessageHeader::Encode(llarp_buffer_t* buf) const
{
if(!EncodeInt(buf, id))
if(!llarp_buffer_put_uint16(buf, id))
return false;
if(!EncodeInt(buf, fields))
if(!llarp_buffer_put_uint16(buf, fields))
return false;
if(!EncodeInt(buf, qd_count))
if(!llarp_buffer_put_uint16(buf, qd_count))
return false;
if(!EncodeInt(buf, an_count))
if(!llarp_buffer_put_uint16(buf, an_count))
return false;
if(!EncodeInt(buf, ns_count))
if(!llarp_buffer_put_uint16(buf, ns_count))
return false;
return EncodeInt(buf, ar_count);
return llarp_buffer_put_uint16(buf, ar_count);
}
bool
MessageHeader::Decode(llarp_buffer_t* buf)
{
if(!DecodeInt(buf, id))
if(!llarp_buffer_read_uint16(buf, &id))
return false;
if(!DecodeInt(buf, fields))
if(!llarp_buffer_read_uint16(buf, &fields))
return false;
if(!DecodeInt(buf, qd_count))
if(!llarp_buffer_read_uint16(buf, &qd_count))
return false;
if(!DecodeInt(buf, an_count))
if(!llarp_buffer_read_uint16(buf, &an_count))
return false;
if(!DecodeInt(buf, ns_count))
if(!llarp_buffer_read_uint16(buf, &ns_count))
return false;
return DecodeInt(buf, ar_count);
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;
@ -64,98 +104,100 @@ namespace llarp
bool
Message::Decode(llarp_buffer_t* buf)
{
if(!hdr.Decode(buf))
return false;
questions.resize(hdr.qd_count);
answers.resize(hdr.an_count);
authorities.resize(hdr.ns_count);
additional.resize(hdr.ar_count);
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::UpdateHeader()
{
hdr.qd_count = questions.size();
hdr.an_count = answers.size();
hdr.ns_count = authorities.size();
hdr.ar_count = additional.size();
}
Message&
Message::AddINReply(llarp::huint32_t ip)
{
if(questions.size())
{
hdr.fields |= (1 << 15);
hdr_fields |= (1 << 15);
const auto& question = questions[0];
answers.emplace_back();
auto& rec = answers.back();
rec.rr_name = question.qname;
rec.rr_type.h = 1;
rec.rr_class = question.qclass;
rec.ttl.h = 1;
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);
UpdateHeader();
answers.emplace_back(std::move(rec));
}
return *this;
}
Message&
void
Message::AddAReply(std::string name)
{
if(questions.size())
{
hdr.fields |= (1 << 15);
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.h = 1;
rec.ttl.h = 1;
auto& rec = answers.back();
rec.rr_name = question.qname;
rec.rr_type = question.qtype;
rec.rr_class = 1;
rec.ttl = 1;
rec.rData.resize(name.size());
memcpy(rec.rData.data(), name.c_str(), rec.rData.size());
UpdateHeader();
}
return *this;
}
Message&
void
Message::AddNXReply()
{
if(questions.size())
{
hdr.fields |= (1 << 15) | (1 << 3);
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.h = 1;
nx.ttl = 1;
nx.rData.resize(1);
nx.rData.data()[0] = 0;
UpdateHeader();
}
return *this;
}
} // namespace dns

View file

@ -18,11 +18,21 @@ namespace llarp
{
l = *buf->cur;
buf->cur++;
if(llarp_buffer_size_left(*buf) < l)
return false;
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 << ".";
ss << ".";
}
buf->cur = buf->cur + l;
} while(l);
name = ss.str();
return true;
@ -31,22 +41,32 @@ namespace llarp
bool
EncodeName(llarp_buffer_t* buf, const Name_t& name)
{
std::stringstream ss(name);
if(name.size() == 0 || name[name.size() - 1] != '.')
ss << ".";
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, '.'))
{
uint8_t l;
if(part.size() > 63)
size_t l = part.length();
if(l > 63)
return false;
l = part.size();
*buf->cur = l;
*(buf->cur) = l;
buf->cur++;
if(llarp_buffer_size_left(*buf) < l)
return false;
memcpy(buf->cur, part.c_str(), l);
if(l)
{
memcpy(buf->cur, part.data(), l);
buf->cur += l;
}
else
break;
}
*buf->cur = 0;
buf->cur++;
return true;
}

View file

@ -1,27 +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(!EncodeInt(buf, qtype))
if(!llarp_buffer_put_uint16(buf, qtype))
return false;
return EncodeInt(buf, qclass);
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(!DecodeInt(buf, qtype))
}
if(!llarp_buffer_read_uint16(buf, &qtype))
{
llarp::LogError("failed to decode type");
return false;
return DecodeInt(buf, qclass);
}
if(!llarp_buffer_read_uint16(buf, &qclass))
{
llarp::LogError("failed to decode class");
return false;
}
return true;
}
} // namespace dns
} // namespace llarp

View file

@ -1,35 +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(!EncodeInt(buf, rr_type))
}
if(!llarp_buffer_put_uint16(buf, rr_type))
{
return false;
if(!EncodeInt(buf, rr_class))
}
if(!llarp_buffer_put_uint16(buf, rr_class))
{
return false;
if(!EncodeInt(buf, ttl))
}
if(!llarp_buffer_put_uint32(buf, ttl))
{
return false;
return EncodeRData(buf, rData);
}
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(!DecodeInt(buf, rr_type))
}
if(!llarp_buffer_read_uint16(buf, &rr_type))
{
llarp::LogError("failed to decode rr type");
return false;
if(!DecodeInt(buf, rr_class))
}
if(!llarp_buffer_read_uint16(buf, &rr_class))
{
llarp::LogError("failed to decode rr class");
return false;
if(!DecodeInt(buf, ttl))
}
if(!llarp_buffer_read_uint32(buf, &ttl))
{
llarp::LogError("failed to decode ttl");
return false;
return DecodeRData(buf, rData);
}
if(!DecodeRData(buf, rData))
{
llarp::LogError("failed to decode rr rdata");
return false;
}
return true;
}
} // namespace dns
} // namespace llarp

View file

@ -5,70 +5,36 @@ namespace llarp
{
namespace dns
{
template <>
bool
DecodeInt(llarp_buffer_t* buf, llarp::huint32_t& i)
{
return llarp_buffer_read_uint32(buf, &i.h);
}
template <>
bool
EncodeInt(llarp_buffer_t* buf, const llarp::huint32_t& i)
{
return llarp_buffer_put_uint32(buf, i.h);
}
template <>
bool
DecodeInt(llarp_buffer_t* buf, llarp::huint16_t& i)
{
return llarp_buffer_read_uint16(buf, &i.h);
}
template <>
bool
EncodeInt(llarp_buffer_t* buf, const llarp::huint16_t& i)
{
return llarp_buffer_put_uint16(buf, i.h);
}
template <>
bool
DecodeInt(llarp_buffer_t* buf, uint16_t& i)
{
return llarp_buffer_read_uint16(buf, &i);
}
template <>
bool
EncodeInt(llarp_buffer_t* buf, const uint16_t& i)
{
return llarp_buffer_put_uint16(buf, i);
}
bool
EncodeRData(llarp_buffer_t* buf, const std::vector< byte_t >& v)
{
if(v.size() > 65536)
return false;
llarp::huint16_t len;
len.h = v.size();
return EncodeInt(buf, len) && llarp_buffer_write(buf, v.data(), v.size());
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)
{
llarp::huint16_t len = {0};
if(!DecodeInt(buf, len))
uint16_t len;
if(!llarp_buffer_read_uint16(buf, &len))
return false;
size_t left = llarp_buffer_size_left(*buf);
if(left < len.h)
if(left < len)
return false;
v.resize(size_t(len.h));
memcpy(v.data(), buf->cur, len.h);
buf->cur += len.h;
v.resize(size_t(len));
if(len)
{
memcpy(v.data(), buf->cur, len);
buf->cur += len;
}
return true;
}

View file

@ -74,17 +74,38 @@ namespace llarp
void
Proxy::HandlePkt(llarp::Addr from, llarp_buffer_t* pkt)
{
Message msg;
if(!msg.Decode(pkt))
MessageHeader hdr;
if(!hdr.Decode(pkt))
{
llarp::LogWarn("failed to handle dns message from ", from);
llarp::DumpBuffer(*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
llarp_ev_udp_sendto(&m_UDP, itr->second, buf);
// remove pending
m_Forwarded.erase(itr);
return;
}
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(
msg,
std::move(msg),
std::bind(&Proxy::SendMessageTo, this, from,
std::placeholders::_1)))
{
@ -92,19 +113,21 @@ namespace llarp
}
return;
}
TX tx = {msg.hdr.id, from};
auto itr = m_Forwarded.find(tx);
if(itr == m_Forwarded.end())
else if(itr == m_Forwarded.end())
{
// new forwarded query
tx.from = PickRandomResolver();
m_Forwarded[tx] = from;
SendMessageTo(tx.from, msg);
llarp_buffer_t buf;
buf.sz = pkt->sz;
buf.base = pkt->base;
buf.cur = buf.base;
// do query
llarp_ev_udp_sendto(&m_UDP, tx.from, buf);
}
else
{
SendMessageTo(itr->second, msg);
m_Forwarded.erase(itr);
// drop (?)
}
}

View file

@ -184,8 +184,9 @@ namespace llarp
return false;
}
std::string qname = msg.questions[0].qname;
if(msg.questions[0].qtype.h == 1)
if(msg.questions[0].qtype == 1)
{
// forward dns
llarp::service::Address addr;
if(addr.FromString(qname, ".loki"))
@ -198,39 +199,50 @@ namespace llarp
}
else if(addr.FromString(qname, ".snode"))
{
// TODO: add hook to EnsurePathToSNode
EnsurePathToSNode(addr.data());
huint32_t ip = ObtainIPForAddr(addr.data(), true);
reply(msg.AddINReply(ip));
msg.AddINReply(ip);
}
else
reply(msg.AddNXReply());
msg.AddNXReply();
reply(msg);
}
else if(msg.questions[0].qtype.h == 12)
else if(msg.questions[0].qtype == 12)
{
// reverse dns
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
{
reply(msg.AddNXReply());
msg.AddNXReply();
reply(msg);
return true;
}
llarp::service::Address addr =
ObtainAddrForIP< llarp::service::Address >(ip, true);
if(!addr.IsZero())
{
reply(msg.AddAReply(addr.ToString(".snode")));
msg.AddAReply(addr.ToString(".snode"));
reply(msg);
return true;
}
addr = ObtainAddrForIP< llarp::service::Address >(ip, false);
if(!addr.IsZero())
{
reply(msg.AddAReply(addr.ToString(".loki")));
msg.AddAReply(addr.ToString(".loki"));
reply(msg);
return true;
}
reply(msg.AddNXReply());
msg.AddNXReply();
reply(msg);
return true;
}
else
reply(msg.AddNXReply());
{
msg.AddNXReply();
reply(msg);
}
return true;
}
@ -244,7 +256,7 @@ namespace llarp
return true;
if(addr.FromString(msg.questions[0].qname, ".snode"))
return true;
if(msg.questions[0].qtype.h == 12)
if(msg.questions[0].qtype == 12)
{
huint32_t ip = {0};
if(!dns::DecodePTR(msg.questions[0].qname, ip))
@ -264,10 +276,13 @@ namespace llarp
if(ctx)
{
huint32_t ip = ObtainIPForAddr(addr.data(), false);
reply(request.AddINReply(ip));
llarp::LogInfo("mapped ", addr, " to ", ip);
request.AddINReply(ip);
}
else
reply(request.AddNXReply());
request.AddNXReply();
reply(request);
}
bool
@ -368,7 +383,6 @@ namespace llarp
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, " on range ",
m_OurRange);
MapAddress(m_Identity.pub.Addr(), m_OurIP, IsSNode());

View file

@ -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;

View file

@ -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
}
};

View file

@ -4,19 +4,15 @@
struct DNSLibTest : public ::testing::Test
{
byte_t mem[1500] = {0};
llarp_buffer_t buf;
byte_t mem[1500];
llarp_buffer_t buf = llarp::StackBuffer< decltype(mem) >(mem);
void
SetUp()
{
buf = llarp::StackBuffer< decltype(mem) >(mem);
}
void
TearDown()
{
buf.sz = sizeof(mem);
Rewind();
memset(mem, '$', sizeof(mem));
}
void
@ -26,6 +22,106 @@ struct DNSLibTest : public ::testing::Test
}
};
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;
@ -40,45 +136,3 @@ TEST_F(DNSLibTest, TestEncodeDecode_RData)
ASSERT_TRUE(llarp::dns::DecodeRData(&buf, other_rdata));
ASSERT_TRUE(rdata == other_rdata);
};
TEST_F(DNSLibTest, TestEncode_huint16)
{
llarp::huint16_t i = {0x1122};
ASSERT_TRUE(llarp::dns::EncodeInt(&buf, i));
ASSERT_TRUE(buf.cur - buf.base == sizeof(uint16_t));
ASSERT_TRUE(buf.base[0] == 0x11);
ASSERT_TRUE(buf.base[1] == 0x22);
};
TEST_F(DNSLibTest, TestEncode_huint32)
{
llarp::huint32_t i = {0x11223344};
ASSERT_TRUE(llarp::dns::EncodeInt(&buf, i));
ASSERT_TRUE(buf.cur - buf.base == sizeof(uint32_t));
ASSERT_TRUE(buf.base[0] == 0x11);
ASSERT_TRUE(buf.base[1] == 0x22);
ASSERT_TRUE(buf.base[2] == 0x33);
ASSERT_TRUE(buf.base[3] == 0x44);
};
TEST_F(DNSLibTest, TestDecode_huint16)
{
llarp::huint16_t i = {0};
buf.base[0] = 0x11;
buf.base[1] = 0x22;
ASSERT_TRUE(llarp::dns::DecodeInt(&buf, i));
ASSERT_TRUE(buf.cur - buf.base == sizeof(uint16_t));
ASSERT_TRUE(i.h == 0x1122);
};
TEST_F(DNSLibTest, TestDecode_huint32)
{
llarp::huint32_t i = {0};
buf.base[0] = 0x11;
buf.base[1] = 0x22;
buf.base[2] = 0x33;
buf.base[3] = 0x44;
ASSERT_TRUE(llarp::dns::DecodeInt(&buf, i));
ASSERT_TRUE(buf.cur - buf.base == sizeof(uint32_t));
ASSERT_TRUE(i.h == 0x11223344);
};