lokinet/llarp/dns/message.cpp

321 lines
8.5 KiB
C++
Raw Normal View History

#include <dns/message.hpp>
#include <dns/dns.hpp>
#include <util/buffer.hpp>
#include <util/endian.hpp>
#include <util/logger.hpp>
2019-02-24 23:46:37 +00:00
#include <util/printer.hpp>
2018-12-04 16:16:43 +00:00
2019-02-02 23:12:42 +00:00
#include <array>
2018-12-03 22:22:59 +00:00
namespace llarp
{
namespace dns
{
bool
MessageHeader::Encode(llarp_buffer_t* buf) const
{
if(!buf->put_uint16(id))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->put_uint16(fields))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->put_uint16(qd_count))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->put_uint16(an_count))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->put_uint16(ns_count))
2018-12-03 22:22:59 +00:00
return false;
return buf->put_uint16(ar_count);
2018-12-03 22:22:59 +00:00
}
bool
MessageHeader::Decode(llarp_buffer_t* buf)
{
if(!buf->read_uint16(id))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->read_uint16(fields))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->read_uint16(qd_count))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->read_uint16(an_count))
2018-12-03 22:22:59 +00:00
return false;
if(!buf->read_uint16(ns_count))
2018-12-03 22:22:59 +00:00
return false;
return buf->read_uint16(ar_count);
2018-12-04 16:16:43 +00:00
}
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))
{
2018-12-03 22:22:59 +00:00
}
bool
Message::Encode(llarp_buffer_t* buf) const
{
2018-12-04 16:16:43 +00:00
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();
2018-12-03 22:22:59 +00:00
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)
2018-12-04 16:16:43 +00:00
{
2018-12-03 22:22:59 +00:00
if(!qd.Decode(buf))
2018-12-04 16:16:43 +00:00
{
llarp::LogError("failed to decode question");
2018-12-03 22:22:59 +00:00
return false;
2018-12-04 16:16:43 +00:00
}
llarp::LogDebug(qd);
}
2018-12-03 22:22:59 +00:00
for(auto& an : answers)
2018-12-04 16:16:43 +00:00
{
2018-12-03 22:22:59 +00:00
if(!an.Decode(buf))
2018-12-04 16:16:43 +00:00
{
llarp::LogError("failed to decode answer");
2018-12-03 22:22:59 +00:00
return false;
2018-12-04 16:16:43 +00:00
}
llarp::LogDebug(an);
}
2018-12-03 22:22:59 +00:00
for(auto& ns : authorities)
2018-12-04 16:16:43 +00:00
{
2018-12-03 22:22:59 +00:00
if(!ns.Decode(buf))
2018-12-04 16:16:43 +00:00
{
llarp::LogError("failed to decode authority");
2018-12-03 22:22:59 +00:00
return false;
2018-12-04 16:16:43 +00:00
}
llarp::LogDebug(ns);
}
2018-12-03 22:22:59 +00:00
for(auto& ar : additional)
2018-12-04 16:16:43 +00:00
{
2018-12-03 22:22:59 +00:00
if(!ar.Decode(buf))
2018-12-04 16:16:43 +00:00
{
llarp::LogError("failed to decode additonal");
2018-12-03 22:22:59 +00:00
return false;
2018-12-04 16:16:43 +00:00
}
llarp::LogDebug(ar);
}
2018-12-03 22:22:59 +00:00
return true;
}
void
Message::AddServFail(RR_TTL_t ttl)
{
if(questions.size())
{
hdr_fields |= flags_RCODEServFail;
// authorative response with recursion available
hdr_fields |= flags_QR | flags_AA | flags_RA;
// don't allow recursion on this request
hdr_fields &= ~flags_RD;
answers.emplace_back();
const auto& question = questions[0];
auto& nx = answers.back();
nx.rr_name = question.qname;
nx.rr_type = question.qtype;
nx.rr_class = question.qclass;
nx.ttl = ttl;
nx.rData.resize(1);
nx.rData.data()[0] = 0;
}
}
2018-12-03 22:22:59 +00:00
void
Message::AddINReply(llarp::huint32_t ip, bool isV6, RR_TTL_t ttl)
2018-12-03 22:22:59 +00:00
{
if(questions.size())
{
2019-03-09 01:19:55 +00:00
hdr_fields |= flags_QR | flags_AA | flags_RA;
2018-12-03 22:22:59 +00:00
const auto& question = questions[0];
2018-12-04 16:16:43 +00:00
ResourceRecord rec;
rec.rr_name = question.qname;
rec.rr_class = qClassIN;
rec.ttl = ttl;
if(isV6)
{
rec.rr_type = qTypeAAAA;
ip.SIIT(rec.rData);
}
else
{
rec.rr_type = qTypeA;
rec.rData.resize(4);
htobe32buf(rec.rData.data(), ip.h);
}
2018-12-04 16:16:43 +00:00
answers.emplace_back(std::move(rec));
2018-12-03 22:22:59 +00:00
}
}
2018-12-04 16:16:43 +00:00
void
Message::AddAReply(std::string name, RR_TTL_t ttl)
2018-12-03 22:22:59 +00:00
{
if(questions.size())
{
2019-03-09 01:19:55 +00:00
hdr_fields |= flags_QR | flags_AA | flags_RA;
2018-12-03 22:22:59 +00:00
const auto& question = questions[0];
answers.emplace_back();
2019-02-02 23:12:42 +00:00
auto& rec = answers.back();
rec.rr_name = question.qname;
rec.rr_type = question.qtype;
rec.rr_class = qClassIN;
rec.ttl = ttl;
2019-02-05 00:29:09 +00:00
std::array< byte_t, 512 > tmp = {{0}};
2019-02-02 23:12:42 +00:00
llarp_buffer_t buf(tmp);
2018-12-04 17:02:13 +00:00
if(EncodeName(&buf, name))
{
buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz);
memcpy(rec.rData.data(), buf.base, buf.sz);
}
2018-12-03 22:22:59 +00:00
}
}
2018-12-13 00:03:19 +00:00
void
Message::AddCNAMEReply(std::string name, RR_TTL_t ttl)
2018-12-13 00:03:19 +00:00
{
if(questions.size())
{
hdr_fields |= flags_QR | flags_AA | flags_RA;
2018-12-13 00:03:19 +00:00
const auto& question = questions[0];
answers.emplace_back();
2019-02-02 23:12:42 +00:00
auto& rec = answers.back();
rec.rr_name = question.qname;
rec.rr_type = qTypeCNAME;
rec.rr_class = qClassIN;
rec.ttl = ttl;
2019-02-05 00:29:09 +00:00
std::array< byte_t, 512 > tmp = {{0}};
2019-02-02 23:12:42 +00:00
llarp_buffer_t buf(tmp);
2018-12-13 00:03:19 +00:00
if(EncodeName(&buf, name))
{
buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz);
memcpy(rec.rData.data(), buf.base, buf.sz);
}
}
}
2018-12-07 21:52:19 +00:00
void
Message::AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl)
2018-12-07 21:52:19 +00:00
{
if(questions.size())
{
2019-02-05 12:52:57 +00:00
hdr_fields |= flags_QR | flags_AA;
2018-12-07 21:52:19 +00:00
const auto& question = questions[0];
answers.emplace_back();
2019-02-02 23:12:42 +00:00
auto& rec = answers.back();
rec.rr_name = question.qname;
rec.rr_type = qTypeMX;
rec.rr_class = qClassIN;
rec.ttl = ttl;
2019-02-05 00:29:09 +00:00
std::array< byte_t, 512 > tmp = {{0}};
2019-02-02 23:12:42 +00:00
llarp_buffer_t buf(tmp);
buf.put_uint16(priority);
2018-12-07 21:52:19 +00:00
if(EncodeName(&buf, name))
{
buf.sz = buf.cur - buf.base;
rec.rData.resize(buf.sz);
memcpy(rec.rData.data(), buf.base, buf.sz);
}
}
}
2018-12-04 16:16:43 +00:00
void
Message::AddNXReply(RR_TTL_t ttl)
2018-12-03 22:22:59 +00:00
{
if(questions.size())
{
2019-02-22 16:18:53 +00:00
// authorative response with recursion available
hdr_fields |= flags_QR | flags_AA | flags_RA;
// don't allow recursion on this request
hdr_fields &= ~flags_RD;
2018-12-03 22:22:59 +00:00
const auto& question = questions[0];
if(question.qtype != qTypeAAAA)
{
2019-02-05 13:42:57 +00:00
hdr_fields |= flags_RCODENameError;
2019-02-05 14:03:38 +00:00
if(question.qtype == qTypeA)
{
answers.emplace_back();
auto& nx = answers.back();
nx.rr_name = question.qname;
nx.rr_type = question.qtype;
nx.rr_class = question.qclass;
nx.ttl = ttl;
nx.rData.resize(1);
nx.rData.data()[0] = 0;
}
}
2018-12-03 22:22:59 +00:00
}
}
2019-02-24 23:46:37 +00:00
std::ostream&
Message::print(std::ostream& stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printAttributeAsHex("dns message id", hdr_id);
printer.printAttributeAsHex("fields", hdr_fields);
printer.printAttribute("questions", questions);
printer.printAttribute("answers", answers);
printer.printAttribute("nameserer", authorities);
printer.printAttribute("additional", additional);
return stream;
}
2018-12-03 22:22:59 +00:00
} // namespace dns
} // namespace llarp