2019-01-10 19:41:51 +00:00
|
|
|
#include <dns/message.hpp>
|
|
|
|
|
2018-12-13 16:14:44 +00:00
|
|
|
#include <dns/dns.hpp>
|
2020-08-31 20:07:17 +00:00
|
|
|
#include <dns/srv_data.hpp>
|
2019-01-10 19:41:51 +00:00
|
|
|
#include <util/buffer.hpp>
|
|
|
|
#include <util/endian.hpp>
|
2019-09-01 12:10:49 +00:00
|
|
|
#include <util/logging/logger.hpp>
|
2019-02-24 23:46:37 +00:00
|
|
|
#include <util/printer.hpp>
|
2019-06-11 16:44:05 +00:00
|
|
|
#include <net/ip.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
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->put_uint16(id))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->put_uint16(fields))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->put_uint16(qd_count))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->put_uint16(an_count))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->put_uint16(ns_count))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2019-02-17 12:13:34 +00:00
|
|
|
return buf->put_uint16(ar_count);
|
2018-12-03 22:22:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
MessageHeader::Decode(llarp_buffer_t* buf)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->read_uint16(id))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->read_uint16(fields))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->read_uint16(qd_count))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->read_uint16(an_count))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->read_uint16(ns_count))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!buf->read_uint16(ar_count))
|
2020-02-12 20:43:37 +00:00
|
|
|
return false;
|
|
|
|
return true;
|
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)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
Message::Message(const MessageHeader& hdr) : hdr_id(hdr.id), hdr_fields(hdr.fields)
|
2018-12-04 16:16:43 +00:00
|
|
|
{
|
2020-02-12 20:43:37 +00:00
|
|
|
questions.resize(size_t(hdr.qd_count));
|
|
|
|
answers.resize(size_t(hdr.an_count));
|
|
|
|
authorities.resize(size_t(hdr.ns_count));
|
|
|
|
additional.resize(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;
|
2020-04-07 18:38:56 +00:00
|
|
|
hdr.id = hdr_id;
|
|
|
|
hdr.fields = hdr_fields;
|
2018-12-04 16:16:43 +00:00
|
|
|
hdr.qd_count = questions.size();
|
|
|
|
hdr.an_count = answers.size();
|
2020-03-09 20:47:27 +00:00
|
|
|
hdr.ns_count = 0;
|
|
|
|
hdr.ar_count = 0;
|
2018-12-04 16:16:43 +00:00
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
if (!hdr.Encode(buf))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& question : questions)
|
|
|
|
if (!question.Encode(buf))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
|
|
|
|
2020-04-07 18:38:56 +00:00
|
|
|
for (const auto& answer : answers)
|
|
|
|
if (!answer.Encode(buf))
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Message::Decode(llarp_buffer_t* buf)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto& qd : questions)
|
2018-12-04 16:16:43 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +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);
|
|
|
|
}
|
2020-04-07 18:38:56 +00:00
|
|
|
for (auto& an : answers)
|
2018-12-04 16:16:43 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not an.Decode(buf))
|
2018-12-04 16:16:43 +00:00
|
|
|
{
|
2020-03-09 20:20:27 +00:00
|
|
|
llarp::LogDebug("failed to decode answer");
|
2018-12-03 22:22:59 +00:00
|
|
|
return false;
|
2018-12-04 16:16:43 +00:00
|
|
|
}
|
|
|
|
}
|
2018-12-03 22:22:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-04-12 12:20:03 +00:00
|
|
|
void Message::AddServFail(RR_TTL_t)
|
2019-04-05 16:39:43 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (questions.size())
|
2019-04-05 16:39:43 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 20:47:27 +00:00
|
|
|
static constexpr uint16_t
|
|
|
|
reply_flags(uint16_t setbits)
|
|
|
|
{
|
|
|
|
return setbits | flags_QR | flags_AA | flags_RA;
|
|
|
|
}
|
|
|
|
|
2018-12-03 22:22:59 +00:00
|
|
|
void
|
2019-06-11 16:44:05 +00:00
|
|
|
Message::AddINReply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (questions.size())
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-03-09 20:47:27 +00:00
|
|
|
hdr_fields = reply_flags(hdr_fields);
|
2018-12-04 16:16:43 +00:00
|
|
|
ResourceRecord rec;
|
2020-04-07 18:38:56 +00:00
|
|
|
rec.rr_name = questions[0].qname;
|
2018-12-13 16:14:44 +00:00
|
|
|
rec.rr_class = qClassIN;
|
2020-04-07 18:38:56 +00:00
|
|
|
rec.ttl = ttl;
|
|
|
|
if (isV6)
|
2019-03-27 13:36:11 +00:00
|
|
|
{
|
|
|
|
rec.rr_type = qTypeAAAA;
|
2019-05-01 13:40:10 +00:00
|
|
|
ip.ToV6(rec.rData);
|
2019-03-27 13:36:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-20 19:14:05 +00:00
|
|
|
const auto addr = net::TruncateV6(ip);
|
2020-04-07 18:38:56 +00:00
|
|
|
rec.rr_type = qTypeA;
|
2019-03-27 13:36:11 +00:00
|
|
|
rec.rData.resize(4);
|
2019-06-11 16:44:05 +00:00
|
|
|
htobe32buf(rec.rData.data(), addr.h);
|
2019-03-27 13:36:11 +00:00
|
|
|
}
|
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
|
2018-12-13 16:14:44 +00:00
|
|
|
Message::AddAReply(std::string name, RR_TTL_t ttl)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (questions.size())
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-03-09 20:47:27 +00:00
|
|
|
hdr_fields = reply_flags(hdr_fields);
|
|
|
|
|
2018-12-03 22:22:59 +00:00
|
|
|
const auto& question = questions[0];
|
|
|
|
answers.emplace_back();
|
2020-04-07 18:38:56 +00:00
|
|
|
auto& rec = answers.back();
|
|
|
|
rec.rr_name = question.qname;
|
|
|
|
rec.rr_type = question.qtype;
|
|
|
|
rec.rr_class = qClassIN;
|
|
|
|
rec.ttl = ttl;
|
|
|
|
std::array<byte_t, 512> tmp = {{0}};
|
2019-02-02 23:12:42 +00:00
|
|
|
llarp_buffer_t buf(tmp);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (EncodeName(&buf, name))
|
2018-12-04 17:02:13 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 20:03:44 +00:00
|
|
|
void
|
|
|
|
Message::AddNSReply(std::string name, RR_TTL_t ttl)
|
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (not questions.empty())
|
2020-03-09 20:03:44 +00:00
|
|
|
{
|
|
|
|
hdr_fields = reply_flags(hdr_fields);
|
|
|
|
|
|
|
|
const auto& question = questions[0];
|
|
|
|
answers.emplace_back();
|
2020-04-07 18:38:56 +00:00
|
|
|
auto& rec = answers.back();
|
|
|
|
rec.rr_name = question.qname;
|
|
|
|
rec.rr_type = qTypeNS;
|
|
|
|
rec.rr_class = qClassIN;
|
|
|
|
rec.ttl = ttl;
|
|
|
|
std::array<byte_t, 512> tmp = {{0}};
|
2020-03-09 20:03:44 +00:00
|
|
|
llarp_buffer_t buf(tmp);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (EncodeName(&buf, name))
|
2020-03-09 20:03:44 +00:00
|
|
|
{
|
|
|
|
buf.sz = buf.cur - buf.base;
|
|
|
|
rec.rData.resize(buf.sz);
|
|
|
|
memcpy(rec.rData.data(), buf.base, buf.sz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-13 00:03:19 +00:00
|
|
|
void
|
2018-12-13 16:14:44 +00:00
|
|
|
Message::AddCNAMEReply(std::string name, RR_TTL_t ttl)
|
2018-12-13 00:03:19 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (questions.size())
|
2018-12-13 00:03:19 +00:00
|
|
|
{
|
2020-03-09 20:47:27 +00:00
|
|
|
hdr_fields = reply_flags(hdr_fields);
|
|
|
|
|
2018-12-13 00:03:19 +00:00
|
|
|
const auto& question = questions[0];
|
|
|
|
answers.emplace_back();
|
2020-04-07 18:38:56 +00:00
|
|
|
auto& rec = answers.back();
|
|
|
|
rec.rr_name = question.qname;
|
|
|
|
rec.rr_type = qTypeCNAME;
|
|
|
|
rec.rr_class = qClassIN;
|
|
|
|
rec.ttl = ttl;
|
|
|
|
std::array<byte_t, 512> tmp = {{0}};
|
2019-02-02 23:12:42 +00:00
|
|
|
llarp_buffer_t buf(tmp);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (EncodeName(&buf, name))
|
2018-12-13 00:03:19 +00:00
|
|
|
{
|
|
|
|
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
|
2018-12-13 16:14:44 +00:00
|
|
|
Message::AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl)
|
2018-12-07 21:52:19 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (questions.size())
|
2018-12-07 21:52:19 +00:00
|
|
|
{
|
2020-03-09 20:47:27 +00:00
|
|
|
hdr_fields = reply_flags(hdr_fields);
|
|
|
|
|
2018-12-07 21:52:19 +00:00
|
|
|
const auto& question = questions[0];
|
|
|
|
answers.emplace_back();
|
2020-04-07 18:38:56 +00:00
|
|
|
auto& rec = answers.back();
|
|
|
|
rec.rr_name = question.qname;
|
|
|
|
rec.rr_type = qTypeMX;
|
|
|
|
rec.rr_class = qClassIN;
|
|
|
|
rec.ttl = ttl;
|
|
|
|
std::array<byte_t, 512> tmp = {{0}};
|
2019-02-02 23:12:42 +00:00
|
|
|
llarp_buffer_t buf(tmp);
|
2019-02-17 12:13:34 +00:00
|
|
|
buf.put_uint16(priority);
|
2020-04-07 18:38:56 +00:00
|
|
|
if (EncodeName(&buf, name))
|
2018-12-07 21:52:19 +00:00
|
|
|
{
|
|
|
|
buf.sz = buf.cur - buf.base;
|
|
|
|
rec.rData.resize(buf.sz);
|
|
|
|
memcpy(rec.rData.data(), buf.base, buf.sz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-31 20:07:17 +00:00
|
|
|
void
|
|
|
|
Message::AddSRVReply(std::vector<SRVData> records, RR_TTL_t ttl)
|
|
|
|
{
|
|
|
|
hdr_fields = reply_flags(hdr_fields);
|
|
|
|
|
|
|
|
const auto& question = questions[0];
|
|
|
|
|
|
|
|
for (const auto& srv : records)
|
|
|
|
{
|
|
|
|
if (not srv.IsValid())
|
|
|
|
{
|
|
|
|
AddNXReply();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
answers.emplace_back();
|
|
|
|
auto& rec = answers.back();
|
|
|
|
rec.rr_name = question.qname;
|
|
|
|
rec.rr_type = qTypeSRV;
|
|
|
|
rec.rr_class = qClassIN;
|
|
|
|
rec.ttl = ttl;
|
|
|
|
|
|
|
|
std::array<byte_t, 512> tmp = {{0}};
|
|
|
|
llarp_buffer_t buf(tmp);
|
|
|
|
|
|
|
|
buf.put_uint16(srv.priority);
|
|
|
|
buf.put_uint16(srv.weight);
|
|
|
|
buf.put_uint16(srv.port);
|
|
|
|
|
|
|
|
std::string target;
|
|
|
|
if (srv.target == "")
|
|
|
|
{
|
|
|
|
// get location of second dot (after service.proto) in qname
|
|
|
|
size_t pos = question.qname.find(".");
|
|
|
|
pos = question.qname.find(".", pos + 1);
|
|
|
|
|
|
|
|
target = question.qname.substr(pos + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
target = srv.target;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not EncodeName(&buf, target))
|
|
|
|
{
|
|
|
|
AddNXReply();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.sz = buf.cur - buf.base;
|
|
|
|
rec.rData.resize(buf.sz);
|
|
|
|
memcpy(rec.rData.data(), buf.base, buf.sz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-12 15:26:20 +00:00
|
|
|
void Message::AddNXReply(RR_TTL_t)
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-04-07 18:38:56 +00:00
|
|
|
if (questions.size())
|
2018-12-03 22:22:59 +00:00
|
|
|
{
|
2020-08-31 20:07:17 +00:00
|
|
|
answers.clear();
|
|
|
|
authorities.clear();
|
|
|
|
additional.clear();
|
|
|
|
|
2019-02-22 16:18:53 +00:00
|
|
|
// authorative response with recursion available
|
2020-03-09 20:47:27 +00:00
|
|
|
hdr_fields = reply_flags(hdr_fields);
|
2019-02-22 16:18:53 +00:00
|
|
|
// don't allow recursion on this request
|
2019-02-05 13:01:56 +00:00
|
|
|
hdr_fields &= ~flags_RD;
|
2019-04-12 15:19:51 +00:00
|
|
|
hdr_fields |= flags_RCODENameError;
|
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
|