mirror of https://github.com/oxen-io/lokinet
prune unused files.
parent
9d494abbaf
commit
fcf0ae2b9e
@ -1,634 +0,0 @@
|
||||
#include <dnsd.hpp> // for llarp_handle_dnsd_recvfrom, dnsc
|
||||
|
||||
#include <util/buffer.hpp>
|
||||
#include <util/endian.hpp>
|
||||
#include <util/logging/logger.hpp>
|
||||
|
||||
void
|
||||
hexDump(const char *buffer, uint16_t size)
|
||||
{
|
||||
// would rather heap allocate than use VLA
|
||||
std::vector< char > hex_buffer(size * 3 + 1);
|
||||
hex_buffer[size * 3] = 0;
|
||||
for(unsigned int j = 0; j < size; j++)
|
||||
sprintf(&hex_buffer[3 * j], "%02X ", buffer[j]);
|
||||
std::string str(hex_buffer.begin(), hex_buffer.end());
|
||||
llarp::LogInfo("First ", size, " bytes: ", str);
|
||||
}
|
||||
|
||||
void
|
||||
hexDumpAt(const char *const buffer, uint32_t pos, uint16_t size)
|
||||
{
|
||||
// would rather heap allocate than use VLA
|
||||
std::vector< char > hex_buffer(size * 3 + 1);
|
||||
hex_buffer[size * 3] = 0;
|
||||
for(unsigned int j = 0; j < size; j++)
|
||||
sprintf(&hex_buffer[3 * j], "%02X ", buffer[pos + j]);
|
||||
std::string str(hex_buffer.begin(), hex_buffer.end());
|
||||
llarp::LogInfo(pos, " ", size, " bytes: ", str);
|
||||
}
|
||||
|
||||
/*
|
||||
<domain-name> is a domain name represented as a series of labels, and
|
||||
terminated by a label with zero length. <character-string> is a single
|
||||
length octet followed by that number of characters. <character-string>
|
||||
is treated as binary information, and can be up to 256 characters in
|
||||
length (including the length octet).
|
||||
*/
|
||||
std::string
|
||||
getDNSstring(const char *const buffer, uint32_t *pos)
|
||||
{
|
||||
std::string str = "";
|
||||
const char *moveable = buffer;
|
||||
moveable += *pos;
|
||||
uint8_t length = *moveable++;
|
||||
(*pos)++;
|
||||
if(length == 0xc0)
|
||||
{
|
||||
uint8_t cPos = *moveable++;
|
||||
(*pos)++;
|
||||
uint32_t cPos32 = cPos;
|
||||
// llarp::LogInfo("Found reference at ", std::to_string(cPos));
|
||||
return getDNSstring(buffer, &cPos32);
|
||||
}
|
||||
// hexDump(moveable, length);
|
||||
// hexDump(buffer, length);
|
||||
// printf("dnsStringLen[%d]\n", length);
|
||||
// llarp::LogInfo("dnsStringLen ", std::to_string(length));
|
||||
if(!length)
|
||||
return str;
|
||||
while(length != 0)
|
||||
{
|
||||
// llarp::LogInfo("Reading ", std::to_string(length));
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
char c = *moveable++;
|
||||
(*pos)++;
|
||||
str.append(1, c);
|
||||
}
|
||||
if(*moveable == '\xc0')
|
||||
{
|
||||
moveable++;
|
||||
(*pos)++; // forward one char
|
||||
uint8_t cPos = *moveable; // read char
|
||||
uint32_t cPos32 = cPos;
|
||||
// llarp::LogInfo("Remaining [", str, "] is an reference at ", (int)cPos);
|
||||
std::string addl = getDNSstring(buffer, &cPos32);
|
||||
// llarp::LogInfo("Addl str [", addl, "]");
|
||||
str += "." + addl;
|
||||
// llarp::LogInfo("Final str [", str, "]");
|
||||
(*pos)++; // move past reference
|
||||
|
||||
return str;
|
||||
}
|
||||
length = *moveable++;
|
||||
(*pos)++;
|
||||
if(length > 64)
|
||||
llarp::LogError("bug detected");
|
||||
// else
|
||||
// hexDump(buffer, length);
|
||||
// llarp::LogInfo("NextLen ", std::to_string(length));
|
||||
if(length != 0)
|
||||
str.append(1, '.');
|
||||
}
|
||||
// llarp::LogInfo("Returning ", str);
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
code_domain(char *&buffer, const std::string &domain) noexcept
|
||||
{
|
||||
std::string::size_type start(0);
|
||||
std::string::size_type end; // indexes
|
||||
// llarp::LogInfo("domain [", domain, "]");
|
||||
while((end = domain.find('.', start)) != std::string::npos)
|
||||
{
|
||||
*buffer++ = end - start; // label length octet
|
||||
for(std::string::size_type i = start; i < end; i++)
|
||||
{
|
||||
*buffer++ = domain[i]; // label octets
|
||||
// llarp::LogInfo("Writing ", domain[i], " at ", i);
|
||||
}
|
||||
start = end + 1; // Skip '.'
|
||||
}
|
||||
|
||||
// llarp::LogInfo("start ", start, " domain size ", domain.size());
|
||||
|
||||
*buffer++ = domain.size() - start; // last label length octet
|
||||
for(size_t i = start; i < domain.size(); i++)
|
||||
{
|
||||
*buffer++ = domain[i]; // last label octets
|
||||
// llarp::LogInfo("Writing ", domain[i], " at ", i);
|
||||
}
|
||||
*buffer++ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
vcode_domain(std::vector< byte_t > &bytes, const std::string &domain) noexcept
|
||||
{
|
||||
std::string::size_type start(0);
|
||||
std::string::size_type end; // indexes
|
||||
// llarp::LogInfo("domain [", domain, "]");
|
||||
while((end = domain.find('.', start)) != std::string::npos)
|
||||
{
|
||||
bytes.push_back(end - start); // label length octet
|
||||
for(std::string::size_type i = start; i < end; i++)
|
||||
{
|
||||
bytes.push_back(domain[i]); // label octets
|
||||
// llarp::LogInfo("Writing ", domain[i], " at ", i);
|
||||
}
|
||||
start = end + 1; // Skip '.'
|
||||
}
|
||||
|
||||
// llarp::LogInfo("start ", start, " domain size ", domain.size());
|
||||
|
||||
bytes.push_back(domain.size() - start); // last label length octet
|
||||
for(size_t i = start; i < domain.size(); i++)
|
||||
{
|
||||
bytes.push_back(domain[i]); // last label octets
|
||||
// llarp::LogInfo("Writing ", domain[i], " at ", i);
|
||||
}
|
||||
bytes.push_back(0); // end it
|
||||
}
|
||||
|
||||
// expects host order
|
||||
void
|
||||
vput16bits(std::vector< byte_t > &bytes, uint16_t value) noexcept
|
||||
{
|
||||
char buf[2] = {0};
|
||||
char *write_buffer = buf;
|
||||
htobe16buf(write_buffer, value);
|
||||
bytes.push_back(buf[0]);
|
||||
bytes.push_back(buf[1]);
|
||||
}
|
||||
|
||||
// expects host order
|
||||
void
|
||||
vput32bits(std::vector< byte_t > &bytes, uint32_t value) noexcept
|
||||
{
|
||||
char buf[4] = {0};
|
||||
char *write_buffer = buf;
|
||||
htobe32buf(write_buffer, value);
|
||||
bytes.push_back(buf[0]);
|
||||
bytes.push_back(buf[1]);
|
||||
bytes.push_back(buf[2]);
|
||||
bytes.push_back(buf[3]);
|
||||
}
|
||||
|
||||
void
|
||||
dns_writeType(std::vector< byte_t > &bytes, llarp::dns::record *record)
|
||||
{
|
||||
auto *type1a = dynamic_cast< llarp::dns::type_1a * >(record);
|
||||
if(type1a)
|
||||
{
|
||||
std::vector< byte_t > more_bytes = type1a->to_bytes();
|
||||
llarp::LogDebug("[1]Adding ", more_bytes.size());
|
||||
bytes.insert(bytes.end(), more_bytes.begin(), more_bytes.end());
|
||||
}
|
||||
|
||||
auto *type2ns = dynamic_cast< llarp::dns::type_2ns * >(record);
|
||||
if(type2ns)
|
||||
{
|
||||
std::vector< byte_t > more_bytes = type2ns->to_bytes();
|
||||
llarp::LogDebug("[2]Adding ", more_bytes.size());
|
||||
bytes.insert(bytes.end(), more_bytes.begin(), more_bytes.end());
|
||||
}
|
||||
|
||||
auto *type5cname = dynamic_cast< llarp::dns::type_5cname * >(record);
|
||||
if(type5cname)
|
||||
{
|
||||
std::vector< byte_t > more_bytes = type5cname->to_bytes();
|
||||
llarp::LogDebug("[5]Adding ", more_bytes.size());
|
||||
bytes.insert(bytes.end(), more_bytes.begin(), more_bytes.end());
|
||||
}
|
||||
|
||||
auto *type12ptr = dynamic_cast< llarp::dns::type_12ptr * >(record);
|
||||
if(type12ptr)
|
||||
{
|
||||
std::vector< byte_t > more_bytes = type12ptr->to_bytes();
|
||||
llarp::LogDebug("[12]Adding ", more_bytes.size());
|
||||
bytes.insert(bytes.end(), more_bytes.begin(), more_bytes.end());
|
||||
}
|
||||
auto *type15mx = dynamic_cast< llarp::dns::type_15mx * >(record);
|
||||
if(type15mx)
|
||||
{
|
||||
std::vector< byte_t > more_bytes = type15mx->to_bytes();
|
||||
llarp::LogDebug("[15]Adding ", more_bytes.size());
|
||||
bytes.insert(bytes.end(), more_bytes.begin(), more_bytes.end());
|
||||
}
|
||||
auto *type16txt = dynamic_cast< llarp::dns::type_16txt * >(record);
|
||||
if(type16txt)
|
||||
{
|
||||
std::vector< byte_t > more_bytes = type16txt->to_bytes();
|
||||
llarp::LogDebug("[15]Adding ", more_bytes.size());
|
||||
bytes.insert(bytes.end(), more_bytes.begin(), more_bytes.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
packet2bytes(dns_packet &in)
|
||||
{
|
||||
std::vector< byte_t > write_buffer;
|
||||
vput16bits(write_buffer, in.header.id);
|
||||
|
||||
int fields = (in.header.qr << 15); // QR => message type, 1 = response
|
||||
fields += (in.header.opcode << 14); // I think opcode is always 0
|
||||
fields += in.header.rcode; // response code (3 => not found, 0 = Ok)
|
||||
vput16bits(write_buffer, fields);
|
||||
|
||||
// don't pull these from the header, trust what we actually have more
|
||||
vput16bits(write_buffer, in.questions.size()); // QD (number of questions)
|
||||
vput16bits(write_buffer, in.answers.size()); // AN (number of answers)
|
||||
vput16bits(write_buffer, in.auth_rrs.size()); // NS (number of auth RRs)
|
||||
vput16bits(write_buffer,
|
||||
in.additional_rrs.size()); // AR (number of Additional RRs)
|
||||
|
||||
for(auto &it : in.questions)
|
||||
{
|
||||
// code question
|
||||
vcode_domain(write_buffer, it->name);
|
||||
vput16bits(write_buffer, it->type);
|
||||
vput16bits(write_buffer, it->qClass);
|
||||
}
|
||||
|
||||
for(auto &it : in.answers)
|
||||
{
|
||||
// code answers
|
||||
vcode_domain(write_buffer, it->name);
|
||||
vput16bits(write_buffer, it->type);
|
||||
vput16bits(write_buffer, it->aClass);
|
||||
vput32bits(write_buffer, 1); // ttl
|
||||
dns_writeType(write_buffer, it->record.get());
|
||||
}
|
||||
|
||||
for(auto &it : in.auth_rrs)
|
||||
{
|
||||
// code answers
|
||||
vcode_domain(write_buffer, it->name);
|
||||
vput16bits(write_buffer, it->type);
|
||||
vput16bits(write_buffer, it->aClass);
|
||||
vput32bits(write_buffer, 1); // ttl
|
||||
dns_writeType(write_buffer, it->record.get());
|
||||
}
|
||||
|
||||
for(auto &it : in.additional_rrs)
|
||||
{
|
||||
// code answers
|
||||
vcode_domain(write_buffer, it->name);
|
||||
vput16bits(write_buffer, it->type);
|
||||
vput16bits(write_buffer, it->aClass);
|
||||
vput32bits(write_buffer, 1); // ttl
|
||||
dns_writeType(write_buffer, it->record.get());
|
||||
}
|
||||
|
||||
return write_buffer;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
uint16_t
|
||||
get16bits(const char *&buffer) noexcept
|
||||
{
|
||||
uint16_t value = bufbe16toh(buffer);
|
||||
buffer += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get32bits(const char *&buffer) noexcept
|
||||
{
|
||||
uint32_t value = bufbe32toh(buffer);
|
||||
buffer += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
bool
|
||||
decode_hdr(llarp_buffer_t *buffer, dns_msg_header *hdr)
|
||||
{
|
||||
uint16_t fields;
|
||||
|
||||
// reads as HOST byte order
|
||||
if(!buffer->read_uint16(hdr->id))
|
||||
return false;
|
||||
if(!buffer->read_uint16(fields))
|
||||
return false;
|
||||
if(!buffer->read_uint16(hdr->qdCount))
|
||||
return false;
|
||||
if(!buffer->read_uint16(hdr->anCount))
|
||||
return false;
|
||||
if(!buffer->read_uint16(hdr->nsCount))
|
||||
return false;
|
||||
if(!buffer->read_uint16(hdr->arCount))
|
||||
return false;
|
||||
|
||||
// decode fields into hdr
|
||||
uint8_t lFields = (fields & 0x00FF) >> 0;
|
||||
uint8_t hFields = (fields & 0xFF00) >> 8;
|
||||
|
||||
// process high byte
|
||||
// hdr->qr = fields & 0x8000;
|
||||
hdr->qr = (hFields >> 7) & 0x1;
|
||||
hdr->opcode = fields & 0x7800;
|
||||
hdr->aa = fields & 0x0400;
|
||||
hdr->tc = fields & 0x0200;
|
||||
hdr->rd = fields & 0x0100;
|
||||
|
||||
// process low byte
|
||||
hdr->ra = (lFields >> 7) & 0x1;
|
||||
hdr->z = (lFields >> 6) & 0x1;
|
||||
hdr->ad = (lFields >> 5) & 0x1;
|
||||
hdr->cd = (lFields >> 4) & 0x1;
|
||||
hdr->rcode = lFields & 0xf;
|
||||
return true;
|
||||
}
|
||||
|
||||
dns_msg_question *
|
||||
decode_question(const char *buffer, uint32_t *pos)
|
||||
{
|
||||
auto *question = new dns_msg_question;
|
||||
|
||||
std::string m_qName = getDNSstring(buffer, pos);
|
||||
llarp::LogDebug("Got question name: ", m_qName);
|
||||
|
||||
const char *moveable = buffer;
|
||||
moveable += *pos; // advance to position
|
||||
question->name = m_qName;
|
||||
|
||||
question->type = get16bits(moveable);
|
||||
(*pos) += 2;
|
||||
question->qClass = get16bits(moveable);
|
||||
(*pos) += 2;
|
||||
return question;
|
||||
}
|
||||
|
||||
dns_msg_answer *
|
||||
decode_answer(const char *const buffer, uint32_t *pos)
|
||||
{
|
||||
auto *answer = new dns_msg_answer;
|
||||
/*
|
||||
llarp_buffer_t bob;
|
||||
bob.base = (unsigned char *)buffer;
|
||||
bob.sz = 12;
|
||||
llarp::DumpBuffer(bob);
|
||||
*/
|
||||
|
||||
const char *moveable = buffer;
|
||||
// llarp::LogDebug("Advancing to pos ", std::to_string(*pos));
|
||||
moveable += (*pos); // advance to position
|
||||
|
||||
// hexDump(moveable, 12);
|
||||
// hexDumpAt(buffer, *pos, 12);
|
||||
|
||||
if(*moveable == '\xc0')
|
||||
{
|
||||
// hexDump(moveable, 2);
|
||||
moveable++;
|
||||
(*pos)++;
|
||||
uint8_t readAt = *moveable;
|
||||
uint32_t readAt32 = readAt;
|
||||
// llarp::LogInfo("Ref, skip. Read ", readAt32);
|
||||
// hexDumpAt(buffer, readAt, 2);
|
||||
answer->name = getDNSstring(buffer, &readAt32);
|
||||
moveable++;
|
||||
(*pos)++;
|
||||
// hexDump(moveable, 10);
|
||||
// hexDumpAt(buffer, *pos, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// get DNSString?
|
||||
llarp::LogWarn("Need to parse string, implement me");
|
||||
/*
|
||||
uint32_t readAt32 = *pos;
|
||||
answer->name = getDNSstring(buffer, &readAt32);
|
||||
llarp::LogInfo("Parsed string ", answer->name, " read ",
|
||||
std::to_string(readAt32)); moveable += readAt32; (*pos) += readAt32;
|
||||
*/
|
||||
// moveable++; (*pos)++;
|
||||
}
|
||||
/*
|
||||
hexDump(moveable, 10);
|
||||
uint8_t first = *moveable++; (*pos)++;
|
||||
llarp::LogInfo("decode - first", std::to_string(first));
|
||||
// SOA hack
|
||||
if(first != 12 && first != 14) // 0x0c (c0 0c) 0
|
||||
{
|
||||
llarp::LogDebug("decode - first isnt 12, stepping back");
|
||||
moveable--; (*pos)--; // rewind buffer one byte
|
||||
}
|
||||
*/
|
||||
// hexDump(moveable, 10);
|
||||
|
||||
answer->type = get16bits(moveable);
|
||||
(*pos) += 2;
|
||||
llarp::LogDebug("Answer Type: ", answer->type);
|
||||
// assert(answer->type < 259);
|
||||
if(answer->type > 259)
|
||||
{
|
||||
llarp::LogWarn("Answer type is off the charts");
|
||||
}
|
||||
answer->aClass = get16bits(moveable);
|
||||
(*pos) += 2;
|
||||
llarp::LogDebug("Answer Class: ", answer->aClass);
|
||||
answer->ttl = get32bits(moveable);
|
||||
(*pos) += 4;
|
||||
llarp::LogDebug("Answer TTL: ", answer->ttl);
|
||||
answer->rdLen = get16bits(moveable);
|
||||
(*pos) += 2;
|
||||
/*
|
||||
llarp::LogDebug("Answer rdL: ", answer->rdLen, " at ",
|
||||
std::to_string(*pos));
|
||||
*/
|
||||
// uint32_t cPos = moveable - buffer;
|
||||
// llarp::LogInfo("pos at ", std::to_string(*pos), " calculated: ",
|
||||
// std::to_string(cPos));
|
||||
|
||||
// hexDump(moveable, answer->rdLen);
|
||||
// hexDumpAt(buffer, *pos, answer->rdLen);
|
||||
if(answer->rdLen == 4)
|
||||
{
|
||||
answer->rData.resize(answer->rdLen);
|
||||
memcpy(answer->rData.data(), moveable, answer->rdLen);
|
||||
/*
|
||||
llarp::LogDebug("Read ", std::to_string(answer->rData[0]), ".",
|
||||
std::to_string(answer->rData[1]), ".",
|
||||
std::to_string(answer->rData[2]), ".",
|
||||
std::to_string(answer->rData[3]));
|
||||
*/
|
||||
moveable += answer->rdLen;
|
||||
(*pos) += answer->rdLen; // advance the length
|
||||
|
||||
answer->record = std::make_unique< llarp::dns::type_1a >();
|
||||
answer->record->parse(answer->rData);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogDebug("Got type ", answer->type);
|
||||
// FIXME: move this out of here, this shouldn't be responsible for decode
|
||||
switch(answer->type)
|
||||
{
|
||||
case LLARP_DNS_RECTYPE_NS: // NS
|
||||
{
|
||||
std::string ns = getDNSstring(buffer, pos);
|
||||
answer->rData.resize(ns.size());
|
||||
memcpy(answer->rData.data(), ns.c_str(),
|
||||
ns.size()); // raw copy rData
|
||||
|
||||
// don't really need to do anything here
|
||||
moveable += answer->rdLen;
|
||||
//(*pos) += answer->rdLen; // advance the length
|
||||
|
||||
answer->record = std::make_unique< llarp::dns::type_2ns >();
|
||||
answer->record->parse(answer->rData);
|
||||
}
|
||||
break;
|
||||
case LLARP_DNS_RECTYPE_CNAME: // CNAME
|
||||
{
|
||||
std::string cname = getDNSstring(buffer, pos);
|
||||
llarp::LogDebug("CNAME ", cname);
|
||||
answer->rData.resize(cname.size());
|
||||
memcpy(answer->rData.data(), cname.c_str(), cname.size());
|
||||
|
||||
moveable += answer->rdLen;
|
||||
//(*pos) += answer->rdLen; // advance the length
|
||||
|
||||
answer->record = std::make_unique< llarp::dns::type_5cname >();
|
||||
answer->record->parse(answer->rData);
|
||||
}
|
||||
break;
|
||||
case LLARP_DNS_RECTYPE_SOA: // type 6 = SOA
|
||||
{
|
||||
// 2 names, then 4x 32bit
|
||||
// why risk any crashes
|
||||
if(answer->rdLen < 24)
|
||||
{
|
||||
llarp::LogWarn("Weird SOA is less than 24 bytes: ", answer->rdLen);
|
||||
}
|
||||
/*
|
||||
std::string mname = getDNSstring((char *)buffer);
|
||||
std::string rname = getDNSstring((char *)buffer);
|
||||
uint32_t serial = get32bits(buffer);
|
||||
uint32_t refresh = get32bits(buffer);
|
||||
uint32_t retry = get32bits(buffer);
|
||||
uint32_t expire = get32bits(buffer);
|
||||
uint32_t minimum = get32bits(buffer);
|
||||
llarp::LogInfo("mname : ", mname);
|
||||
llarp::LogInfo("rname : ", rname);
|
||||
llarp::LogDebug("serial : ", serial);
|
||||
llarp::LogDebug("refresh : ", refresh);
|
||||
llarp::LogDebug("retry : ", retry);
|
||||
llarp::LogDebug("expire : ", expire);
|
||||
llarp::LogDebug("minimum : ", minimum);
|
||||
*/
|
||||
moveable += answer->rdLen;
|
||||
(*pos) += answer->rdLen; // advance the length
|
||||
}
|
||||
break;
|
||||
case LLARP_DNS_RECTYPE_PTR:
|
||||
{
|
||||
std::string revname = getDNSstring(buffer, pos);
|
||||
llarp::LogInfo("revDNSname: ", revname);
|
||||
// answer->rData = new uint8_t[answer->rdLen + 1];
|
||||
answer->rData.resize(revname.size());
|
||||
memcpy(answer->rData.data(), revname.c_str(), revname.size());
|
||||
// answer->rData = (uint8_t *)strdup(revname.c_str()); // safer? nope
|
||||
moveable += answer->rdLen;
|
||||
//(*pos) += answer->rdLen; // advance the length
|
||||
|
||||
answer->record = std::make_unique< llarp::dns::type_12ptr >();
|
||||
answer->record->parse(answer->rData);
|
||||
}
|
||||
break;
|
||||
case LLARP_DNS_RECTYPE_MX:
|
||||
{
|
||||
uint16_t priority = get16bits(moveable);
|
||||
(*pos) += 2;
|
||||
std::string revname = getDNSstring(buffer, pos);
|
||||
llarp::LogInfo("MX: ", revname, " @ ", priority);
|
||||
// answer->rData = new uint8_t[revname.length() + 1];
|
||||
// memcpy(answer->rData, revname.c_str(), answer->rdLen);
|
||||
answer->rData.resize(revname.size());
|
||||
memcpy(answer->rData.data(), revname.c_str(), revname.size());
|
||||
moveable += answer->rdLen - 2; // advance the length
|
||||
// llarp::LogInfo("leaving at ", std::to_string(*pos));
|
||||
// hexDumpAt(buffer, *pos, 5);
|
||||
// hexDump(moveable, 5);
|
||||
|
||||
answer->record = std::make_unique< llarp::dns::type_15mx >();
|
||||
answer->record->parse(answer->rData);
|
||||
}
|
||||
break;
|
||||
case LLARP_DNS_RECTYPE_TXT:
|
||||
{
|
||||
// hexDump(buffer, 5);
|
||||
// std::string revname = getDNSstring((char *)buffer);
|
||||
llarp::LogInfo("TXT: size: ", answer->rdLen);
|
||||
answer->rData.resize(answer->rdLen);
|
||||
memcpy(answer->rData.data(), moveable + 1, answer->rdLen);
|
||||
moveable += answer->rdLen;
|
||||
(*pos) += answer->rdLen; // advance the length
|
||||
|
||||
answer->record = std::make_unique< llarp::dns::type_16txt >();
|
||||
answer->record->parse(answer->rData);
|
||||
}
|
||||
break;
|
||||
// type 28 AAAA
|
||||
default:
|
||||
moveable += answer->rdLen;
|
||||
(*pos) += answer->rdLen; // advance the length
|
||||
llarp::LogWarn("Unknown Type ", answer->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
void
|
||||
put16bits(char *&buffer, uint16_t value) noexcept
|
||||
{
|
||||
htobe16buf(buffer, value);
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
void
|
||||
put32bits(char *&buffer, uint32_t value) noexcept
|
||||
{
|
||||
htobe32buf(buffer, value);
|
||||
buffer += 4;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_handle_dns_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *addr, ManagedBuffer buf)
|
||||
{
|
||||
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
|
||||
dns_msg_header hdr;
|
||||
if(!decode_hdr(&buf.underlying, &hdr))
|
||||
{
|
||||
llarp::LogError("failed to decode dns header");
|
||||
return;
|
||||
}
|
||||
// rewind
|
||||
buf.underlying.cur = buf.underlying.base;
|
||||
llarp::LogDebug("msg id ", hdr.id);
|
||||
llarp::LogDebug("msg qr ", (uint8_t)hdr.qr);
|
||||
if(!udp)
|
||||
{
|
||||
llarp::LogError("no udp passed in to handler");
|
||||
}
|
||||
if(!addr)
|
||||
{
|
||||
llarp::LogError("no source addr passed in to handler");
|
||||
}
|
||||
if(hdr.qr)
|
||||
{
|
||||
llarp::LogDebug("handling as dnsc answer");
|
||||
llarp_handle_dnsc_recvfrom(udp, addr, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogDebug("handling as dnsd question");
|
||||
llarp_handle_dnsd_recvfrom(udp, addr, buf);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#ifndef LLARP_DNS_H_
|
||||
#define LLARP_DNS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
/**
|
||||
* dns.h
|
||||
*
|
||||
* dns client/server
|
||||
*/
|
||||
|
||||
// fwd declr
|
||||
struct dnsc_answer_request;
|
||||
|
||||
using dnsc_answer_hook_func = void (*)(dnsc_answer_request *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -1,152 +0,0 @@
|
||||
#ifndef LLARP_DNS_HPP
|
||||
#define LLARP_DNS_HPP
|
||||
|
||||
#include <dns.h>
|
||||
#include <sys/types.h> // for uint & ssize_t
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <dns/rectypes.hpp>
|
||||
#include <net/net.hpp> // for llarp::Addr , llarp::huint32_t
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define LLARP_DNS_RECTYPE_A 1
|
||||
#define LLARP_DNS_RECTYPE_NS 2
|
||||
#define LLARP_DNS_RECTYPE_CNAME 5
|
||||
#define LLARP_DNS_RECTYPE_SOA 6
|
||||
#define LLARP_DNS_RECTYPE_PTR 12
|
||||
#define LLARP_DNS_RECTYPE_MX 15
|
||||
#define LLARP_DNS_RECTYPE_TXT 16
|
||||
|
||||
struct dnsc_answer_request;
|
||||
struct dnsd_context;
|
||||
|
||||
// dnsc can work over any UDP socket
|
||||
// however we can't ignore udp->user
|
||||
// we need to be able to reference the request (being a request or response)
|
||||
// bottom line is we can't use udp->user
|
||||
// so we'll need to track all incoming and outgoing requests
|
||||
struct dns_tracker
|
||||
{
|
||||
// uint c_responses;
|
||||
uint32_t c_requests;
|
||||
// request has to be a pointer
|
||||
std::unordered_map< uint32_t, std::unique_ptr< dnsc_answer_request > >
|
||||
client_request;
|
||||
// FIXME: support multiple dns server contexts
|
||||
dnsd_context *dnsd;
|
||||
// rn we need 1 tracker per DNSd and each DNSd needs it's own IP
|
||||
// actually we can bind once and use the tracker to sort
|
||||
// but no way to tell what DNSd they want...
|
||||
// std::map< llarp::Addr, std::unique_ptr< dnsc_answer_request > > dnsds;
|
||||
// std::map< uint, dnsd_question_request * > daemon_request;
|
||||
};
|
||||
|
||||
// protocol parsing/writing structures & functions
|
||||
struct dns_msg_header
|
||||
{
|
||||
uint16_t id;
|
||||
|
||||
uint8_t qr : 1;
|
||||
uint8_t opcode : 4;
|
||||
uint8_t aa : 1;
|
||||
uint8_t tc : 1;
|
||||
uint8_t rd : 1;
|
||||
|
||||
uint8_t ra : 1;
|
||||
uint8_t z : 1;
|
||||
uint8_t ad : 1;
|
||||
uint8_t cd : 1;
|
||||
uint8_t rcode : 4;
|
||||
|
||||
uint16_t
|
||||
fields() const
|
||||
{
|
||||
return (qr << 15) | (opcode << 14) | (aa << 10) | (tc << 9)
|
||||
| (rd << 8) << (ra << 7) | (z << 6) | rcode;
|
||||
}
|
||||
|
||||
uint16_t qdCount;
|
||||
uint16_t anCount;
|
||||
uint16_t nsCount;
|
||||
uint16_t arCount;
|
||||
};
|
||||
|
||||
struct dns_msg_question
|
||||
{
|
||||
std::string name;
|
||||
uint16_t type;
|
||||
uint16_t qClass;
|
||||
};
|
||||
|
||||
struct dns_msg_answer
|
||||
{
|
||||
std::string name;
|
||||
uint16_t type;
|
||||
uint16_t aClass;
|
||||
uint32_t ttl;
|
||||
uint16_t rdLen;
|
||||
std::vector< byte_t > rData;
|
||||
std::unique_ptr< llarp::dns::record > record;
|
||||
};
|
||||
|
||||
struct dns_packet
|
||||
{
|
||||
struct dns_msg_header header;
|
||||
std::vector< std::unique_ptr< dns_msg_question > > questions;
|
||||
std::vector< std::unique_ptr< dns_msg_answer > > answers;
|
||||
std::vector< std::unique_ptr< dns_msg_answer > > auth_rrs;
|
||||
std::vector< std::unique_ptr< dns_msg_answer > > additional_rrs;
|
||||
};
|
||||
|
||||
std::vector< byte_t >
|
||||
packet2bytes(dns_packet &in);
|
||||
|
||||
std::string
|
||||
getDNSstring(const char *const buffer, uint32_t *pos);
|
||||
|
||||
void
|
||||
code_domain(char *&buffer, const std::string &domain) noexcept;
|
||||
|
||||
void
|
||||
vcode_domain(std::vector< byte_t > &bytes, const std::string &domain) noexcept;
|
||||
|
||||
void
|
||||
vput16bits(std::vector< byte_t > &bytes, uint16_t value) noexcept;
|
||||
|
||||
void
|
||||
vput32bits(std::vector< byte_t > &bytes, uint32_t value) noexcept;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
uint16_t
|
||||
get16bits(const char *&buffer) noexcept;
|
||||
|
||||
uint32_t
|
||||
get32bits(const char *&buffer) noexcept;
|
||||
|
||||
bool
|
||||
decode_hdr(llarp_buffer_t *buffer, dns_msg_header *hdr);
|
||||
|
||||
dns_msg_question *
|
||||
decode_question(const char *buffer, uint32_t *pos);
|
||||
|
||||
dns_msg_answer *
|
||||
decode_answer(const char *const buffer, uint32_t *pos);
|
||||
|
||||
void
|
||||
put16bits(char *&buffer, uint16_t value) noexcept;
|
||||
|
||||
void
|
||||
put32bits(char *&buffer, uint32_t value) noexcept;
|
||||
|
||||
void
|
||||
llarp_handle_dns_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *addr, ManagedBuffer buf);
|
||||
}
|
||||
#endif
|
@ -1,213 +0,0 @@
|
||||
#include <dns.hpp> // for vput16bits()
|
||||
#include <dns/rectypes.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dns
|
||||
{
|
||||
record::~record() = default;
|
||||
|
||||
bool
|
||||
record::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
return bytes.size() ? true : false;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
record::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
type_1a::type_1a() : record()
|
||||
{
|
||||
this->ipaddr.h = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
type_1a::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
if(bytes.size() < 4)
|
||||
{
|
||||
LogWarn("Less than 4 bytes passed in");
|
||||
return false;
|
||||
}
|
||||
// endian problems? no, it should come in, in network order
|
||||
/*
|
||||
LogDebug("Read ", std::to_string(bytes[0]), ".",
|
||||
std::to_string(bytes[1]), ".",
|
||||
std::to_string(bytes[2]), ".",
|
||||
std::to_string(bytes[3]));
|
||||
*/
|
||||
this->ipaddr = ipaddr_ipv4_bits(bytes[3], bytes[2], bytes[1], bytes[0]);
|
||||
// LogDebug("Test ", this->ipaddr);
|
||||
return bytes.size() ? true : false;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
type_1a::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
vput16bits(retval, 4); // rdLength
|
||||
vput32bits(retval, this->ipaddr.h); // write IP
|
||||
return retval;
|
||||
}
|
||||
|
||||
type_2ns::type_2ns() : record()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
type_2ns::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
// trim last 2 bytes... probably the size
|
||||
this->ns = std::string(reinterpret_cast< char* >(bytes.data()),
|
||||
bytes.size() - 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
type_2ns::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
vput16bits(retval, 2 + this->ns.length()); // rdLength
|
||||
vcode_domain(retval, this->ns);
|
||||
return retval;
|
||||
}
|
||||
|
||||
type_5cname::type_5cname() : record()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
type_5cname::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
// trim last 2 bytes... probably the size
|
||||
this->cname =
|
||||
std::string(reinterpret_cast< char* >(bytes.data()), bytes.size());
|
||||
// LogDebug("type5 parsed ", this->cname);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
type_5cname::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
vput16bits(retval, 2 + this->cname.length()); // rdLength
|
||||
vcode_domain(retval, this->cname);
|
||||
return retval;
|
||||
}
|
||||
|
||||
type_6soa::type_6soa() : record()
|
||||
{
|
||||
this->serial = 0;
|
||||
this->refresh = 0;
|
||||
this->retry = 0;
|
||||
this->expire = 0;
|
||||
this->minimum = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
type_6soa::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
// FIXME: implmement me
|
||||
// this->cname = std::string(reinterpret_cast<char *>(bytes.data()),
|
||||
// bytes.size());
|
||||
return bytes.size() ? true : false;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
type_6soa::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
vput16bits(
|
||||
retval,
|
||||
4 + this->mname.length() + this->rname.length() + 20); // rdLength
|
||||
vcode_domain(retval, this->mname);
|
||||
vcode_domain(retval, this->rname);
|
||||
vput32bits(retval, this->serial);
|
||||
vput32bits(retval, this->refresh);
|
||||
vput32bits(retval, this->retry);
|
||||
vput32bits(retval, this->expire);
|
||||
vput32bits(retval, this->minimum);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
type_12ptr::type_12ptr() : record()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
type_12ptr::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
this->revname =
|
||||
std::string(reinterpret_cast< char* >(bytes.data()), bytes.size());
|
||||
return bytes.size() ? true : false;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
type_12ptr::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
// revname has 2 extra bytes at the end we don't want or need
|
||||
vput16bits(retval, 2 + this->revname.length()); // rdLength
|
||||
vcode_domain(retval, this->revname);
|
||||
// vput16bits(retval, this->revname.length()); // rdLength
|
||||
// vcode_domain(retval, this->revname.substr(0, this->revname.size() -
|
||||
// 2));
|
||||
return retval;
|
||||
}
|
||||
|
||||
type_15mx::type_15mx() : record()
|
||||
{
|
||||
this->priority = 99;
|
||||
}
|
||||
|
||||
bool
|
||||
type_15mx::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
this->mx =
|
||||
std::string(reinterpret_cast< char* >(bytes.data()), bytes.size());
|
||||
// LogInfo("parsed ", this->mx);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
type_15mx::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
vput16bits(retval, 2 + (2 + this->mx.length())); // rdLength
|
||||
vput16bits(retval, this->priority); // priority
|
||||
vcode_domain(retval, this->mx);
|
||||
return retval;
|
||||
}
|
||||
|
||||
type_16txt::type_16txt() : record()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
type_16txt::parse(std::vector< byte_t > bytes)
|
||||
{
|
||||
this->txt = std::string(reinterpret_cast< char* >(bytes.data()),
|
||||
bytes.size() - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector< byte_t >
|
||||
type_16txt::to_bytes()
|
||||
{
|
||||
std::vector< byte_t > retval;
|
||||
vput16bits(retval, 1 + this->txt.length()); // rdLength
|
||||
retval.push_back(this->txt.length()); // length
|
||||
for(auto it : this->txt)
|
||||
{
|
||||
retval.push_back(it);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
} // namespace dns
|
||||
} // namespace llarp
|
@ -1,133 +0,0 @@
|
||||
#ifndef LLARP_DNS_REC_TYPES_HPP
|
||||
#define LLARP_DNS_REC_TYPES_HPP
|
||||
|
||||
#include <net/net.hpp> // for llarp::Addr , llarp::huint32_t
|
||||
#include <util/types.hpp> // for byte_t
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dns
|
||||
{
|
||||
struct record
|
||||
{
|
||||
virtual ~record() = 0;
|
||||
record() = default;
|
||||
|
||||
virtual bool
|
||||
parse(std::vector< byte_t > bytes) = 0;
|
||||
|
||||
virtual std::vector< byte_t >
|
||||
to_bytes() = 0;
|
||||
};
|
||||
|
||||
struct type_1a : public record
|
||||
{
|
||||
huint32_t ipaddr;
|
||||
|
||||
~type_1a() override = default;
|
||||
type_1a();
|
||||
|
||||
bool
|
||||
parse(std::vector< byte_t > bytes) override;
|
||||
|
||||
std::vector< byte_t >
|
||||
to_bytes() override;
|
||||
};
|
||||
|
||||
struct type_2ns : public record
|
||||
{
|
||||
std::string ns;
|
||||
|
||||
~type_2ns() override = default;
|
||||
type_2ns();
|
||||
|
||||
bool
|
||||
parse(std::vector< byte_t > bytes) override;
|
||||
|
||||
std::vector< byte_t >
|
||||
to_bytes() override;
|
||||
};
|
||||
|
||||
struct type_6soa : public record
|
||||
{
|
||||
std::string mname;
|
||||
std::string rname;
|
||||
uint32_t serial;
|
||||
uint32_t refresh;
|
||||
uint32_t retry;
|
||||
uint32_t expire;
|
||||
uint32_t minimum;
|
||||
|
||||
~type_6soa() override = default;
|
||||
type_6soa();
|
||||
|
||||
bool
|
||||
parse(std::vector< byte_t > bytes) override;
|
||||
|
||||
std::vector< byte_t >
|
||||
to_bytes() override;
|
||||
};
|
||||
|
||||
struct type_5cname : public record
|
||||
{
|
||||
std::string cname;
|
||||
|
||||
~type_5cname() override = default;
|
||||
type_5cname();
|
||||
|
||||
bool
|
||||
parse(std::vector< byte_t > bytes) override;
|
||||
|
||||
std::vector< byte_t >
|
||||
to_bytes() override;
|
||||
};
|
||||
|
||||
struct type_12ptr : public record
|
||||
{
|
||||
std::string revname;
|
||||
|
||||
~type_12ptr() override = default;
|
||||
type_12ptr();
|
||||
|
||||
bool
|
||||
parse(std::vector< byte_t > bytes) override;
|
||||
|
||||
std::vector< byte_t >
|
||||
to_bytes() override;
|
||||
};
|
||||
|
||||
struct type_15mx : public record
|
||||
{
|
||||
std::string mx;
|
||||
uint16_t priority;
|
||||
|
||||
~type_15mx() override = default;
|
||||
type_15mx();
|
||||
|
||||
bool
|
||||
parse(std::vector< byte_t > bytes) override;
|
||||
|
||||
std::vector< byte_t >
|
||||
to_bytes() override;
|
||||
};
|
||||
|
||||
struct type_16txt : public record
|
||||
{
|
||||
std::string txt;
|
||||
|
||||
~type_16txt() override = default;
|
||||
type_16txt();
|
||||
|
||||
bool
|
||||
parse(std::vector< byte_t > bytes) override;
|
||||
|
||||
std::vector< byte_t >
|
||||
to_bytes() override;
|
||||
};
|
||||
|
||||
} // namespace dns
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -1,819 +0,0 @@
|
||||
#include <dnsc.hpp>
|
||||
#include <net/net.hpp> // for llarp::Addr
|
||||
#include <util/logging/logger.hpp>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h> /* getaddrinfo, getnameinfo */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h> /* close */
|
||||
#endif
|
||||
|
||||
#include <cstdlib> /* exit */
|
||||
#include <cstring> /* memset */
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm> // for std::find_if
|
||||
#include <cstdio> // sprintf
|
||||
|
||||
dns_tracker dns_udp_tracker;
|
||||
|
||||
/*
|
||||
#define DNC_BUF_SIZE 512
|
||||
/// a question to be asked remotely (the actual bytes to send on the wire)
|
||||
// header, question
|
||||
struct dns_query
|
||||
{
|
||||
uint16_t length;
|
||||
// char *url;
|
||||
unsigned char request[DNC_BUF_SIZE];
|
||||
// uint16_t reqType;
|
||||
};
|
||||
*/
|
||||
|
||||
/// build a DNS question packet
|
||||
struct dns_query *
|
||||
build_dns_packet(char *url, uint16_t id, uint16_t reqType)
|
||||
{
|
||||
auto *dnsQuery = new dns_query;
|
||||
dnsQuery->length = 12;
|
||||
// ID
|
||||
// buffer[0] = (value & 0xFF00) >> 8;
|
||||
// buffer[1] = value & 0xFF;
|
||||
llarp::LogDebug("building request ", id);
|
||||
|
||||
dnsQuery->request[0] = (id & 0xFF00) >> 8;
|
||||
dnsQuery->request[1] = (id & 0x00FF) >> 0;
|
||||
// field
|
||||
dnsQuery->request[2] = 0x01;
|
||||
dnsQuery->request[3] = 0x00;
|
||||
// questions
|
||||
dnsQuery->request[4] = 0x00;
|
||||
dnsQuery->request[5] = 0x01;
|
||||
// answers
|
||||
dnsQuery->request[6] = 0x00;
|
||||
dnsQuery->request[7] = 0x00;
|
||||
// ns
|
||||
dnsQuery->request[8] = 0x00;
|
||||
dnsQuery->request[9] = 0x00;
|
||||
// ar
|
||||
dnsQuery->request[10] = 0x00;
|
||||
dnsQuery->request[11] = 0x00;
|
||||
|
||||
char *word;
|
||||
// llarp::LogDebug("Asking DNS server %s about %s", SERVER, dnsQuery->url);
|
||||
|
||||
char *strTemp = strdup(url);
|
||||
|
||||
word = strtok(strTemp, ".");
|
||||
while(word)
|
||||
{
|
||||
// llarp::LogDebug("parsing hostname: \"%s\" is %zu characters", word,
|
||||
// strlen(word));
|
||||
dnsQuery->request[dnsQuery->length++] = strlen(word);
|
||||
for(unsigned int i = 0; i < strlen(word); i++)
|
||||
{
|
||||
dnsQuery->request[dnsQuery->length++] = word[i];
|
||||
}
|
||||
word = strtok(nullptr, ".");
|
||||
}
|
||||
free(strTemp);
|
||||
dnsQuery->request[dnsQuery->length++] = 0x00; // End of the host name
|
||||
dnsQuery->request[dnsQuery->length++] =
|
||||
0x00; // 0x0001 - Query is a Type A query (host address)
|
||||
dnsQuery->request[dnsQuery->length++] = reqType;
|
||||
dnsQuery->request[dnsQuery->length++] =
|
||||
0x00; // 0x0001 - Query is class IN (Internet address)
|
||||
dnsQuery->request[dnsQuery->length++] = 0x01;
|
||||
return dnsQuery;
|
||||
}
|
||||
|
||||
dns_query *
|
||||
answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url,
|
||||
dnsc_answer_hook_func resolved, void *user, uint16_t type)
|
||||
{
|
||||
std::unique_ptr< dnsc_answer_request > request(new dnsc_answer_request);
|
||||
if(!request)
|
||||
{
|
||||
llarp::LogError("Couldn't make dnsc request");
|
||||
return nullptr;
|
||||
}
|
||||
request->sock = sock;
|
||||
request->user = user;
|
||||
request->resolved = resolved;
|
||||
request->found = false;
|
||||
request->context = dnsc;
|
||||
|
||||
char *sUrl = strdup(url);
|
||||
request->question.name = (char *)sUrl; // since it's a std::String
|
||||
// we can nuke sUrl now
|
||||
free(sUrl);
|
||||
|
||||
// leave 256 bytes available
|
||||
if(request->question.name.size() > 255)
|
||||
{
|
||||
// size_t diff = request->question.name.size() - 255;
|
||||
// request->question.name = request->question.name.substr(diff); // get the
|
||||
// rightmost 255 bytes
|
||||
llarp::LogWarn("dnsc request question too long");
|
||||
return nullptr;
|
||||
}
|
||||
request->question.type = type;
|
||||
request->question.qClass = 1;
|
||||
|
||||
// register our self with the tracker
|
||||
dns_tracker *tracker = request->context->tracker;
|
||||
if(!tracker)
|
||||
{
|
||||
llarp::LogError("no tracker in DNSc context");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16_t id = ++tracker->c_requests;
|
||||
if(id == 65535)
|
||||
id = 0;
|
||||
// conflict: do we need this?
|
||||
// tracker->client_request[id] = std::unique_ptr< dnsc_answer_request
|
||||
// >(request);
|
||||
|
||||
dns_query *dns_packet = build_dns_packet(
|
||||
(char *)request->question.name.c_str(), id, request->question.type);
|
||||
|
||||
tracker->client_request[id] = std::move(request);
|
||||
|
||||
return dns_packet;
|
||||
}
|
||||
|
||||
// FIXME: make first a std_unique
|
||||
/// generic dnsc handler
|
||||
void
|
||||
generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
|
||||
const llarp_buffer_t &buffer, dns_msg_header *hdr)
|
||||
{
|
||||
if(!request)
|
||||
{
|
||||
llarp::LogError(
|
||||
"User data to DNS Client response not a dnsc_answer_request");
|
||||
// we can't call back the hook
|
||||
return;
|
||||
}
|
||||
// llarp::LogInfo("got a response, udp user is ", udp->user);
|
||||
|
||||
// unsigned char *castBuf = (unsigned char *)buf;
|
||||
// const char *const castBufc = (const char *)buf;
|
||||
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
|
||||
size_t sz = buffer.sz;
|
||||
|
||||
llarp::LogDebug("Header got client responses for id: ", hdr->id);
|
||||
// llarp_dnsc_unbind(request);
|
||||
|
||||
// unsigned char *castBuf = (unsigned char *)buf;
|
||||
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
|
||||
|
||||
// hexdump("received packet", &buffer, ret);
|
||||
/*
|
||||
uint16_t QDCOUNT; // No. of items in Question Section
|
||||
uint16_t ANCOUNT; // No. of items in Answer Section
|
||||
uint16_t NSCOUNT; // No. of items in Authority Section
|
||||
uint16_t ARCOUNT; // No. of items in Additional Section
|
||||
uint16_t QCLASS; // Specifies the class of the query
|
||||
uint16_t ATYPE; // Specifies the meaning of the data in the RDATA field
|
||||
uint16_t ACLASS; // Specifies the class of the data in the RDATA field
|
||||
uint32_t TTL; // The number of seconds the results can be cached
|
||||
uint16_t RDLENGTH; // The length of the RDATA field
|
||||
uint16_t MSGID;
|
||||
*/
|
||||
uint8_t rcode;
|
||||
// int length;
|
||||
|
||||
// struct dns_query *dnsQuery = &request->query;
|
||||
|
||||
// rcode = (buffer[3] & 0x0F);
|
||||
// llarp::LogInfo("dnsc rcode ", rcode);
|
||||
|
||||
// dns_msg_header *msg = decode_hdr((const char *)castBuf);
|
||||
// dns_msg_header *msg = hdr;
|
||||
// castBuf += 12;
|
||||
llarp::LogDebug("msg id ", hdr->id);
|
||||
uint8_t qr = hdr->qr;
|
||||
llarp::LogDebug("msg qr ", qr);
|
||||
uint8_t opcode = hdr->opcode;
|
||||
llarp::LogDebug("msg op ", opcode);
|
||||
rcode = hdr->rcode;
|
||||
llarp::LogDebug("msg rc ", rcode);
|
||||
|
||||
llarp::LogDebug("msg qdc ", hdr->qdCount);
|
||||
llarp::LogDebug("msg anc ", hdr->anCount);
|
||||
llarp::LogDebug("msg nsc ", hdr->nsCount);
|
||||
llarp::LogDebug("msg arc ", hdr->arCount);
|
||||
|
||||
// FIXME: only handling one atm
|
||||
uint32_t pos = 12; // just set after header
|
||||
dns_msg_question *question = nullptr;
|
||||
for(uint32_t i = 0; i < hdr->qdCount; i++)
|
||||
{
|
||||
question = decode_question((char *)buffer.base, &pos);
|
||||
request->packet.questions.emplace_back(question);
|
||||
// llarp::LogDebug("Read a question, now at ", std::to_string(pos));
|
||||
// 1 dot: 1 byte for length + length
|
||||
// 4 bytes for class/type
|
||||
// castBuf += question->name.length() + 1 + 4;
|
||||
// castBuf += 2; // skip answer label
|
||||
}
|
||||
if(question)
|
||||
{
|
||||
llarp::LogDebug("Question ", std::to_string(question->type), " ",
|
||||
question->name);
|
||||
}
|
||||
// FIXME: only handling one atm
|
||||
std::vector< dns_msg_answer * > answers;
|
||||
dns_msg_answer *answer = nullptr;
|
||||
for(uint32_t i = 0; i < hdr->anCount; i++)
|
||||
{
|
||||
// pos = 0; // reset pos
|
||||
answer = decode_answer((char *)buffer.base, &pos);
|
||||
answers.push_back(answer);
|
||||
request->packet.answers.emplace_back(answer);
|
||||
/*
|
||||
llarp::LogDebug("Read an answer ", answer->type, " for ",
|
||||
request->question.name, ", now at ", std::to_string(pos));
|
||||
*/
|
||||
// llarp::LogInfo("Read an answer. Label Len: ", answer->name.length(), "
|
||||
// rdLen: ", answer->rdLen);
|
||||
// name + Type (2) + Class (2) + TTL (4) + rdLen (2) + rdData + skip next
|
||||
// answer label (1) first 2 was answer->name.length() if lbl is ref and type
|
||||
// 1: it should be 16 bytes long l0 + t2 + c2 + t4 + l2 + rd4 (14) + l2
|
||||
// (2)
|
||||
/*
|
||||
castBuf += 0 + 2 + 2 + 4 + 2 + answer->rdLen;
|
||||
castBuf += 2; // skip answer label
|
||||
uint8_t first = *castBuf;
|
||||
if(first != 0)
|
||||
{
|
||||
llarp::LogDebug("next byte isnt 12, skipping ahead one byte. ",
|
||||
std::to_string(first));
|
||||
castBuf++;
|
||||
}
|
||||
*/
|
||||
// prevent reading past the end of the packet
|
||||
/*
|
||||
auto diff = castBuf - (unsigned char *)buf;
|
||||
llarp::LogDebug("Read answer, bytes left ", diff);
|
||||
if(diff > sz)
|
||||
{
|
||||
// llarp::LogWarn("Would read past end of dns packet. for ",
|
||||
// request->question.name);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
if(pos > (size_t)sz)
|
||||
{
|
||||
llarp::LogWarn("Would read past end of dns packet. for ",
|
||||
request->question.name);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
uint8_t first = castBufc[pos];
|
||||
if(first != 0)
|
||||
{
|
||||
llarp::LogInfo("next byte isnt 12, skipping ahead one byte. ",
|
||||
std::to_string(first));
|
||||
pos++;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// handle authority records (usually no answers with these, so we'll just
|
||||
// stomp) usually NS records tho
|
||||
for(uint32_t i = 0; i < hdr->nsCount; i++)
|
||||
{
|
||||
// pos = 0; // reset pos
|
||||
answer = decode_answer((char *)buffer.base, &pos);
|
||||
request->packet.answers.emplace_back(answer);
|
||||
// answers.push_back(answer);
|
||||
/*
|
||||
llarp::LogDebug("Read an authority for ",
|
||||
request->question.name, " at ", std::to_string(pos));
|
||||
*/
|
||||
// castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
|
||||
if((size_t)pos > sz)
|
||||
{
|
||||
llarp::LogWarn("Would read past end of dns packet. for ",
|
||||
request->question.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < hdr->arCount; i++)
|
||||
{
|
||||
answer = decode_answer((char *)buffer.base, &pos);
|
||||
request->packet.answers.emplace_back(answer);
|
||||
/*
|
||||
llarp::LogDebug("Read an addl RR for ",
|
||||
request->question.name, " at ", std::to_string(pos));
|
||||
*/
|
||||
// castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
|
||||
if((size_t)pos > sz)
|
||||
{
|
||||
llarp::LogWarn("Would read past end of dns packet. for ",
|
||||
request->question.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
size_t i = 0;
|
||||
for(auto it = answers.begin(); it != answers.end(); ++it)
|
||||
{
|
||||
llarp::LogInfo("Answer #", i, " class: [", (*it)->aClass, "] type: [",
|
||||
(*it)->type,
|
||||
"] rdlen[", (*it)->rdLen, "]");
|
||||
i++;
|
||||
}
|
||||
*/
|
||||
|
||||
// dns_msg_answer *answer2 = decode_answer((const char*)castBuf);
|
||||
// castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
|
||||
|
||||
// llarp::LogDebug("query type: %u\n", dnsQuery->reqType);
|
||||
/*
|
||||
QCLASS = (uint16_t)dnsQuery->request[dnsQuery->length - 2] * 0x100
|
||||
+ dnsQuery->request[dnsQuery->length - 1];
|
||||
llarp::LogInfo("query class: ", QCLASS);
|
||||
|
||||
length = dnsQuery->length + 1; // to skip 0xc00c
|
||||
// printf("length [%d] from [%d]\n", length, buffer.base);
|
||||
ATYPE = (uint16_t)buffer[length + 1] * 0x100 + buffer[length + 2];
|
||||
llarp::LogInfo("answer type: ", ATYPE);
|
||||
ACLASS = (uint16_t)buffer[length + 3] * 0x100 + buffer[length + 4];
|
||||
llarp::LogInfo("answer class: ", ACLASS);
|
||||
TTL = (uint32_t)buffer[length + 5] * 0x1000000 + buffer[length + 6] * 0x10000
|
||||
+ buffer[length + 7] * 0x100 + buffer[length + 8];
|
||||
llarp::LogInfo("seconds to cache: ", TTL);
|
||||
RDLENGTH = (uint16_t)buffer[length + 9] * 0x100 + buffer[length + 10];
|
||||
llarp::LogInfo("bytes in answer: ", RDLENGTH);
|
||||
|
||||
MSGID = (uint16_t)buffer[0] * 0x100 + buffer[1];
|
||||
// llarp::LogDebug("answer msg id: %u\n", MSGID);
|
||||
*/
|
||||
llarp::Addr upstreamAddr = request->context->resolvers[0];
|
||||
|
||||
if(answer == nullptr)
|
||||
{
|
||||
llarp::LogWarn("nameserver ", upstreamAddr,
|
||||
" didnt return any answers for ",
|
||||
question ? question->name : "null question");
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
if(answer->type == 5 || answer->type == 2)
|
||||
{
|
||||
llarp::LogDebug("Last answer is a cname/NS, reverting to first");
|
||||
answer = answers.front();
|
||||
}
|
||||
|
||||
if(question)
|
||||
{
|
||||
llarp::LogDebug("qus type ", question->type);
|
||||
}
|
||||
|
||||
llarp::LogDebug("ans class ", answer->aClass);
|
||||
llarp::LogDebug("ans type ", answer->type);
|
||||
llarp::LogDebug("ans ttl ", answer->ttl);
|
||||
llarp::LogDebug("ans rdlen ", answer->rdLen);
|
||||
|
||||
/*
|
||||
llarp::LogInfo("ans2 class ", answer2->aClass);
|
||||
llarp::LogInfo("ans2 type ", answer2->type);
|
||||
llarp::LogInfo("ans2 ttl ", answer2->ttl);
|
||||
llarp::LogInfo("ans2 rdlen ", answer2->rdLen);
|
||||
*/
|
||||
|
||||
// llarp::LogDebug("rcode ", std::to_string(rcode));
|
||||
if(rcode == 2)
|
||||
{
|
||||
llarp::LogWarn("nameserver ", upstreamAddr, " returned SERVFAIL:");
|
||||
llarp::LogWarn(
|
||||
" the name server was unable to process this query due to a problem "
|
||||
"with the name server.");
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
if(rcode == 3)
|
||||
{
|
||||
llarp::LogWarn("nameserver ", upstreamAddr,
|
||||
" returned NXDOMAIN for: ", request->question.name);
|
||||
llarp::LogWarn(" the domain name referenced in the query does not exist");
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
|
||||
int ip = 0;
|
||||
|
||||
// if no answer, just bail now
|
||||
if(!answer)
|
||||
{
|
||||
request->found = false;
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
|
||||
/* search for and print IPv4 addresses */
|
||||
// if(dnsQuery->reqType == 0x01)
|
||||
/*
|
||||
llarp::LogDebug("request question type: ",
|
||||
std::to_string(request->question.type));
|
||||
*/
|
||||
// lets detect this for a bit
|
||||
if(answer->type != question->type)
|
||||
{
|
||||
llarp::LogWarn("Answer type [", std::to_string(answer->type),
|
||||
"] doesn't match question type[",
|
||||
std::to_string(question->type), "]");
|
||||
}
|
||||
// check this assumption
|
||||
if(request->question.type != question->type)
|
||||
{
|
||||
llarp::LogWarn("Request qtype [", std::to_string(request->question.type),
|
||||
"] doesn't match response qtype[",
|
||||
std::to_string(question->type), "]");
|
||||
}
|
||||
if(answer->type == 1)
|
||||
{
|
||||
// llarp::LogInfo("DNS server's answer is: (type#=", ATYPE, "):");
|
||||
llarp::LogDebug("IPv4 address(es) for ", request->question.name, ":");
|
||||
|
||||
// llarp::LogDebug("Answer rdLen ", std::to_string(answer->rdLen));
|
||||
if(answer->rdLen == 4)
|
||||
{
|
||||
/*
|
||||
request->result.sa_family = AF_INET;
|
||||
#if((__APPLE__ && __MACH__) || __FreeBSD__)
|
||||
request->result.sa_len = sizeof(in_addr);
|
||||
#endif
|
||||
struct in_addr *addr =
|
||||
&((struct sockaddr_in *)&request->result)->sin_addr;
|
||||
|
||||
unsigned char *ip = (unsigned char *)&(addr->s_addr);
|
||||
ip[0] = answer->rData[0];
|
||||
ip[1] = answer->rData[1];
|
||||
ip[2] = answer->rData[2];
|
||||
ip[3] = answer->rData[3];
|
||||
*/
|
||||
|
||||
/*
|
||||
request->result.from_4int(answer->rData[0], answer->rData[1],
|
||||
answer->rData[2], answer->rData[3]);
|
||||
*/
|
||||
// llarp::LogDebug("Passing back IPv4: ",
|
||||
// std::to_string(answer->rData[3]), ".",
|
||||
// std::to_string(answer->rData[2]),
|
||||
// ".", std::to_string(answer->rData[1]), ".",
|
||||
// std::to_string(answer->rData[0]));
|
||||
/*
|
||||
request->result =
|
||||
llarp::ipaddr_ipv4_bits(answer->rData[3], answer->rData[2],
|
||||
answer->rData[1], answer->rData[0]);
|
||||
*/
|
||||
|
||||
// llarp::Addr test(request->result);
|
||||
// llarp::LogDebug(request->result);
|
||||
request->found = true;
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ip)
|
||||
{
|
||||
llarp::LogWarn(" No IPv4 address found in the DNS answer!");
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(answer->type == 12)
|
||||
{
|
||||
llarp::LogDebug("Resolving PTR");
|
||||
// llarp::dns::type_12ptr *record = dynamic_cast< llarp::dns::type_12ptr *
|
||||
// >(answer->record.get());
|
||||
request->found = true;
|
||||
// request->revDNS = std::string((char *)answer->rData.data(),
|
||||
// answer->rData.size());
|
||||
// request->revDNS = record->revname;
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
else if(answer->type == 15)
|
||||
{
|
||||
auto *record =
|
||||
dynamic_cast< llarp::dns::type_15mx * >(answer->record.get());
|
||||
llarp::LogDebug("Resolving MX ", record->mx, "@", record->priority);
|
||||
request->found = true;
|
||||
// request->result.h = record->priority;
|
||||
// request->revDNS = std::string((char *)answer->rData.data(),
|
||||
// answer->rData.size());
|
||||
// request->revDNS = record->mx;
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
else if(answer->type == 16)
|
||||
{
|
||||
llarp::LogDebug("Resolving TXT");
|
||||
request->found = true;
|
||||
// request->revDNS = std::string((char *)answer->rData.data(),
|
||||
// answer->rData.size());
|
||||
request->resolved(request);
|
||||
return;
|
||||
}
|
||||
else if(answer->type == 28)
|
||||
{
|
||||
llarp::LogDebug("Resolving AAAA");
|
||||
return;
|
||||
}
|
||||
llarp::LogWarn("Unhandled question type ", request->question.type);
|
||||
// should we let it timeout? lets try sending 404 asap
|
||||
request->resolved(request);
|
||||
}
|
||||
|
||||
void
|
||||
raw_resolve_host(struct dnsc_context *const dnsc, const char *url,
|
||||
dnsc_answer_hook_func resolved, void *const user,
|
||||
uint16_t type)
|
||||
{
|
||||
if(strstr(url, "in-addr.arpa") != nullptr)
|
||||
{
|
||||
type = 12;
|
||||
}
|
||||
dns_query *dns_packet =
|
||||
answer_request_alloc(dnsc, nullptr, url, resolved, user, type);
|
||||
if(!dns_packet)
|
||||
{
|
||||
llarp::LogError("Couldn't make dnsc packet");
|
||||
return;
|
||||
}
|
||||
|
||||
// char *word;
|
||||
llarp::Addr upstreamAddr = dnsc->resolvers[0];
|
||||
llarp::LogDebug("Asking DNS server ", upstreamAddr, " about ", url);
|
||||
|
||||
struct sockaddr_in addr;
|
||||
ssize_t ret;
|
||||
socklen_t size;
|
||||
// int length;
|
||||
unsigned char buffer[DNC_BUF_SIZE];
|
||||
#ifndef _WIN32
|
||||
int sockfd;
|
||||
#else
|
||||
SOCKET sockfd;
|
||||
#endif
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(!(sockfd > 0))
|
||||
{
|
||||
llarp::LogWarn("Error creating socket!\n");
|
||||
delete dns_packet;
|
||||
return;
|
||||
}
|
||||
// socket = sockfd;
|
||||
sockaddr_in *dnscSock = ((sockaddr_in *)dnsc->resolvers[0].addr4());
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = dnscSock->sin_addr.s_addr;
|
||||
addr.sin_port = dnscSock->sin_port;
|
||||
size = sizeof(addr);
|
||||
|
||||
// hexdump("sending packet", &dnsQuery.request, dnsQuery.length);
|
||||
|
||||
ret = sendto(sockfd, (const char *)dns_packet->request, dns_packet->length, 0,
|
||||
(struct sockaddr *)&addr, size);
|
||||
|
||||
delete dns_packet;
|
||||
if(ret < 0)
|
||||
{
|
||||
llarp::LogWarn("Error Sending Request");
|
||||
return;
|
||||
}
|
||||
llarp::LogInfo("Sent");
|
||||
|
||||
memset(&buffer, 0, DNC_BUF_SIZE);
|
||||
llarp::LogInfo("Waiting for recv");
|
||||
|
||||
// Timeout?
|
||||
ret = recvfrom(sockfd, (char *)buffer, DNC_BUF_SIZE, 0,
|
||||
(struct sockaddr *)&addr, &size);
|
||||
llarp::LogInfo("recv done ", size);
|
||||
if(ret < 0)
|
||||
{
|
||||
llarp::LogWarn("Error Receiving Response");
|
||||
return;
|
||||
}
|
||||
llarp::LogInfo("closing new socket\n");
|
||||
if(!size)
|
||||
{
|
||||
llarp::LogWarn("Error Receiving DNS Client Response");
|
||||
return;
|
||||
}
|
||||
// hexdump("received packet", &buffer, ret);
|
||||
|
||||
#ifndef _WIN32
|
||||
close(sockfd);
|
||||
#else
|
||||
closesocket(sockfd);
|
||||
#endif
|
||||
|
||||
llarp_buffer_t lbuffer;
|
||||
lbuffer.base = (byte_t *)buffer;
|
||||
lbuffer.cur = lbuffer.base;
|
||||
lbuffer.sz = size;
|
||||
|
||||
// unsigned char *castBuf = (unsigned char *)buffer;
|
||||
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
|
||||
dns_msg_header hdr;
|
||||
if(!decode_hdr(&lbuffer, &hdr))
|
||||
{
|
||||
llarp::LogError("failed to decode dns header");
|
||||
return;
|
||||
}
|
||||
|
||||
llarp::LogInfo("response header says it belongs to id #", hdr.id);
|
||||
|
||||
// if we sent this out, then there's an id
|
||||
auto *tracker = (struct dns_tracker *)dnsc->tracker;
|
||||
struct dnsc_answer_request *request = tracker->client_request[hdr.id].get();
|
||||
|
||||
if(request)
|
||||
{
|
||||
request->packet.header = hdr;
|
||||
generic_handle_dnsc_recvfrom(tracker->client_request[hdr.id].get(), lbuffer,
|
||||
&hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("Ignoring multiple responses on ID #", hdr.id);
|
||||
}
|
||||
}
|
||||
|
||||
/// intermediate udp_io handler
|
||||
void
|
||||
llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp,
|
||||
const struct sockaddr *saddr, ManagedBuffer buf)
|
||||
{
|
||||
if(!saddr)
|
||||
{
|
||||
llarp::LogWarn("saddr isnt set");
|
||||
}
|
||||
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
|
||||
dns_msg_header hdr;
|
||||
if(!decode_hdr(&buf.underlying, &hdr))
|
||||
{
|
||||
llarp::LogError("failed to decode dns header");
|
||||
return;
|
||||
}
|
||||
buf.underlying.cur = buf.underlying.base; // reset cursor to beginning
|
||||
|
||||
llarp::LogDebug("Header got client responses for id: ", hdr.id);
|
||||
|
||||
// if we sent this out, then there's an id
|
||||
auto *tracker = (struct dns_tracker *)udp->user;
|
||||
struct dnsc_answer_request *request = tracker->client_request[hdr.id].get();
|
||||
|
||||
// sometimes we'll get double responses
|
||||
if(request)
|
||||
{
|
||||
generic_handle_dnsc_recvfrom(request, buf, &hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("Ignoring multiple responses on ID #", hdr.id);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_resolve_host(struct dnsc_context *const dnsc, const char *url,
|
||||
dnsc_answer_hook_func resolved, void *const user,
|
||||
uint16_t type)
|
||||
{
|
||||
// FIXME: probably can be stack allocated
|
||||
/*
|
||||
if (strstr(url, "in-addr.arpa") != nullptr)
|
||||
{
|
||||
type = 12;
|
||||
}
|
||||
*/
|
||||
dns_query *dns_packet =
|
||||
answer_request_alloc(dnsc, &dnsc->udp, url, resolved, user, type);
|
||||
if(!dns_packet)
|
||||
{
|
||||
llarp::LogError("Couldn't make dnsc packet");
|
||||
return false;
|
||||
}
|
||||
|
||||
// register request with udp response tracker
|
||||
// dns_tracker *tracker = (dns_tracker *)dnsc->udp->user;
|
||||
|
||||
/*
|
||||
uint16_t length = 0;
|
||||
dns_msg_header header;
|
||||
header.id = htons(id);
|
||||
header.qr = 0;
|
||||
header.opcode = 0;
|
||||
header.aa = 0;
|
||||
header.tc = 0;
|
||||
header.rd = 1;
|
||||
header.ra = 0;
|
||||
header.rcode = 0;
|
||||
header.qdCount = htons(1);
|
||||
header.anCount = 0;
|
||||
header.nsCount = 0;
|
||||
header.arCount = 0;
|
||||
length += 12;
|
||||
|
||||
//request->question.name = sUrl;
|
||||
request->question.type = htons(1);
|
||||
request->question.qClass = htons(1);
|
||||
|
||||
uint16_t qLen = request->question.name.length() + 8;
|
||||
length += qLen;
|
||||
|
||||
unsigned char bytes[length];
|
||||
// memcpy isn't going to fix the network endian issue
|
||||
// encode header into bytes
|
||||
memcpy(bytes, &header, 12);
|
||||
// encode question into bytes
|
||||
memcpy(bytes + 12, &request->question, qLen);
|
||||
*/
|
||||
|
||||
// uint16_t id = ++tracker->c_requests;
|
||||
// tracker->client_request[id] = request;
|
||||
// llarp::LogInfo("Sending request #", tracker->c_requests, " ", length, "
|
||||
// bytes");
|
||||
|
||||
// ssize_t ret = llarp_ev_udp_sendto(dnsc->udp, dnsc->server, bytes, length);
|
||||
ssize_t ret = llarp_ev_udp_sendto(
|
||||
dnsc->udp, dnsc->resolvers[0],
|
||||
llarp_buffer_t(dns_packet->request, dns_packet->length));
|
||||
delete dns_packet;
|
||||
if(ret < 0)
|
||||
{
|
||||
llarp::LogWarn("Error Sending Request");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_host_resolved(dnsc_answer_request *const request)
|
||||
{
|
||||
auto *tracker = (dns_tracker *)request->context->tracker;
|
||||
auto val = std::find_if(
|
||||
tracker->client_request.begin(), tracker->client_request.end(),
|
||||
[request](
|
||||
std::pair< const uint32_t, std::unique_ptr< dnsc_answer_request > >
|
||||
&element) { return element.second.get() == request; });
|
||||
if(val != tracker->client_request.end())
|
||||
{
|
||||
tracker->client_request[val->first].reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("Couldn't disable ", request);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_dnsc_init(struct dnsc_context *const dnsc, llarp::Logic *const logic,
|
||||
struct llarp_ev_loop *const netloop,
|
||||
const llarp::Addr &dnsc_sockaddr)
|
||||
{
|
||||
// create client socket
|
||||
if(netloop)
|
||||
{
|
||||
if(!dnsc->udp)
|
||||
{
|
||||
llarp::LogError("DNSc udp isn't set");
|
||||
return false;
|
||||
}
|
||||
llarp::Addr dnsc_srcsockaddr(0, 0, 0, 0, 0); // just find a public udp port
|
||||
int bind_res = llarp_ev_add_udp(netloop, dnsc->udp,
|
||||
(const sockaddr *)dnsc_srcsockaddr);
|
||||
if(bind_res == -1)
|
||||
{
|
||||
llarp::LogError("Couldn't bind to ", dnsc_srcsockaddr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
llarp::LogInfo("DNSc adding relay ", dnsc_sockaddr);
|
||||
dnsc->resolvers.push_back(dnsc_sockaddr);
|
||||
dnsc->tracker = &dns_udp_tracker;
|
||||
dnsc->logic = logic;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_dnsc_stop(ABSL_ATTRIBUTE_UNUSED struct dnsc_context *const dnsc)
|
||||
{
|
||||
// delete(sockaddr_in *)dnsc->server; // deallocation
|
||||
return true;
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
#ifndef LLARP_DNSC_HPP
|
||||
#define LLARP_DNSC_HPP
|
||||
|
||||
#include <dns.hpp> // get protocol structs
|
||||
#include <ev/ev.h> // for sockaadr
|
||||
|
||||
// internal, non-public functions
|
||||
// well dnsc init/stop are public...
|
||||
|
||||
struct dnsc_answer_request;
|
||||
|
||||
#define DNC_BUF_SIZE 512
|
||||
/// a question to be asked remotely (the actual bytes to send on the wire)
|
||||
// header, question
|
||||
struct dns_query
|
||||
{
|
||||
uint16_t length;
|
||||
unsigned char request[DNC_BUF_SIZE];
|
||||
// char *url;
|
||||
// uint16_t reqType;
|
||||
};
|
||||
|
||||
struct dns_query *
|
||||
build_dns_packet(char *url, uint16_t id, uint16_t reqType);
|
||||
|
||||
/// hook function to handle an dns client request
|
||||
// should we pass by llarp::Addr
|
||||
// not as long as we're supporting raw
|
||||
using dnsc_answer_hook_func = void (*)(dnsc_answer_request *);
|
||||
|
||||
/// struct for dns client requests
|
||||
struct dnsc_answer_request
|
||||
{
|
||||
/// sock type
|
||||
void *sock; // points to udp that sent the request to DNSc...
|
||||
/// customizable (used for hook (outer request))
|
||||
void *user;
|
||||
/// request storage
|
||||
dns_msg_question question;
|
||||
/// response storage
|
||||
dns_packet packet;
|
||||
/// hook
|
||||
dnsc_answer_hook_func resolved;
|
||||
/// result
|
||||
bool found;
|
||||
|
||||
// llarp::huint32_t result;
|
||||
// std::string revDNS;
|
||||
|
||||
// a reference to dnsc_context incase of multiple contexts
|
||||
struct dnsc_context *context;
|
||||
};
|
||||
|
||||
/// event handler for processing DNS responses
|
||||
void
|
||||
llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp,
|
||||
const struct sockaddr *addr, ManagedBuffer buf);
|
||||
|
||||
/// generic handler for processing DNS responses
|
||||
/// this doesn't look like it exists
|
||||
/// that's because raw_resolve_host calls generic_handle_dnsc_recvfrom directly
|
||||
/// because we don't need a callback like recvfrom
|
||||
/// because we're not evented
|
||||
/// however daemon/dns expects this
|
||||
/*
|
||||
void
|
||||
raw_handle_recvfrom(int *sockfd, const struct sockaddr *addr, const void *buf,
|
||||
const ssize_t sz);
|
||||
*/
|
||||
|
||||
// removed saddr, if needed get through request
|
||||
void
|
||||
generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
|
||||
const llarp_buffer_t &buffer, dns_msg_header *hdr);
|
||||
|
||||
/// DNS client context (one needed per upstream DNS server)
|
||||
struct dnsc_context
|
||||
{
|
||||
/// Target: DNS servers to use
|
||||
std::vector< llarp::Addr > resolvers;
|
||||
/// udp tracker
|
||||
struct dns_tracker *tracker;
|
||||
/// sock type
|
||||
void *sock;
|
||||
// where to create the new sockets
|
||||
struct llarp_udp_io *udp;
|
||||
/// We will likely need something for timing events (timeouts)
|
||||
llarp::Logic *logic;
|
||||
};
|
||||
|
||||
/// async (blocking w/callback) resolve a hostname using generic socks
|
||||
void
|
||||
raw_resolve_host(struct dnsc_context *const dnsc, const char *url,
|
||||
dnsc_answer_hook_func resolved, void *const user,
|
||||
uint16_t type);
|
||||
|
||||
/// async (non blocking w/callback) resolve a hostname using llarp platform
|
||||
/// framework
|
||||
bool
|
||||
llarp_resolve_host(struct dnsc_context *const dns, const char *url,
|
||||
dnsc_answer_hook_func resolved, void *const user,
|
||||
uint16_t type);
|
||||
|
||||
/// cleans up request structure allocations
|
||||
void
|
||||
llarp_host_resolved(dnsc_answer_request *const request);
|
||||
|
||||
/// initialize dns subsystem and bind socket
|
||||
/// returns true on bind success otherwise returns false
|
||||
bool
|
||||
llarp_dnsc_init(struct dnsc_context *const dnsc, llarp::Logic *const logic,
|
||||
struct llarp_ev_loop *const netloop,
|
||||
const llarp::Addr &dnsc_sockaddr);
|
||||
|
||||
/// shutdowns any events, and deallocates for this context
|
||||
bool
|
||||
llarp_dnsc_stop(struct dnsc_context *const dnsc);
|
||||
|
||||
#endif
|
@ -1,612 +0,0 @@
|
||||
#include <dnsd.hpp>
|
||||
|
||||
#include <util/buffer.hpp>
|
||||
#include <net/net.hpp>
|
||||
|
||||
extern dns_tracker dns_udp_tracker;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define MIN wmin
|
||||
#endif
|
||||
|
||||
constexpr size_t BUFFER_SIZE = 1500;
|
||||
|
||||
ssize_t
|
||||
raw_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
|
||||
ManagedBuffer buf)
|
||||
{
|
||||
int *fd = (int *)sock;
|
||||
// how do we get to these??
|
||||
socklen_t addrLen = sizeof(struct sockaddr_in);
|
||||
return sendto(*fd, (const char *)buf.underlying.base, buf.underlying.sz, 0,
|
||||
from, addrLen);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
llarp_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
|
||||
ManagedBuffer buf)
|
||||
{
|
||||
auto *udp = (struct llarp_udp_io *)sock;
|
||||
if(!udp)
|
||||
{
|
||||
llarp::LogWarn("couldnt cast to udp");
|
||||
return 0;
|
||||
}
|
||||
// llarp::LogInfo("hook sending ", udp, " bytes: ", length);
|
||||
// udp seems ok
|
||||
// this call isn't calling the function...
|
||||
// llarp::ev_io * evio = static_cast< llarp::ev_io * >(udp->impl);
|
||||
// printf("ev_io[%x]\n", evio);
|
||||
return llarp_ev_udp_sendto(udp, from, buf.underlying);
|
||||
}
|
||||
|
||||
void
|
||||
write404_dnss_response(const dnsd_question_request *request)
|
||||
{
|
||||
char buf[BUFFER_SIZE] = {0};
|
||||
|
||||
char *write_buffer = buf;
|
||||
char *bufferBegin = buf;
|
||||
// build header
|
||||
put16bits(write_buffer, request->hdr.id);
|
||||
// not found flag set
|
||||
put16bits(write_buffer, (1 << 15) | request->hdr.fields() | 3);
|
||||
|
||||
put16bits(write_buffer, 1); // QD (number of questions)
|
||||
put16bits(write_buffer, 1); // AN (number of answers)
|
||||
put16bits(write_buffer, 0); // NS (number of auth RRs)
|
||||
put16bits(write_buffer, 0); // AR (number of Additional RRs)
|
||||
|
||||
// code question
|
||||
code_domain(write_buffer, request->question.name);
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
|
||||
// code answer
|
||||
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
put16bits(write_buffer, 1); // rdLength
|
||||
*write_buffer++ = 0; // write a null byte
|
||||
|
||||
uint32_t out_bytes = write_buffer - bufferBegin;
|
||||
llarp::LogDebug("Sending 404, ", out_bytes, " bytes");
|
||||
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
|
||||
request->sendto_hook(request->user, request->from,
|
||||
ManagedBuffer(llarp_buffer_t(buf, out_bytes)));
|
||||
}
|
||||
|
||||
void
|
||||
writecname_dnss_response(std::string cname,
|
||||
const dnsd_question_request *request)
|
||||
{
|
||||
char buf[BUFFER_SIZE] = {0};
|
||||
|
||||
char *write_buffer = buf;
|
||||
char *bufferBegin = buf;
|
||||
// build header
|
||||
put16bits(write_buffer, request->hdr.id);
|
||||
// fields |= 1UL << 7; // RA recursion available
|
||||
// fields |= 1UL << 8; // RD recursion desired
|
||||
// fields |= 1UL << 9; // 9 is truncate, forces TCP
|
||||
put16bits(write_buffer, request->hdr.fields() | (1 << 15));
|
||||
|
||||
put16bits(write_buffer, 1); // QD (number of questions)
|
||||
put16bits(write_buffer, 1); // AN (number of answers)
|
||||
put16bits(write_buffer, 1); // NS (number of auth RRs)
|
||||
put16bits(write_buffer, 1); // AR (number of Additional RRs)
|
||||
|
||||
// code question
|
||||
code_domain(write_buffer, request->question.name);
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
|
||||
// code answer
|
||||
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, 5); // cname
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
|
||||
put16bits(write_buffer, cname.length() + 2); // rdLength
|
||||
code_domain(write_buffer, cname); //
|
||||
// location of cname
|
||||
//*write_buffer++ = ip[0];
|
||||
//*write_buffer++ = ip[1];
|
||||
|
||||
// write auth RR
|
||||
code_domain(write_buffer, cname); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, 2); // NS
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
|
||||
std::string local("ns1.loki");
|
||||
put16bits(write_buffer, local.length() + 2); // rdLength
|
||||
code_domain(write_buffer, local); // com, type=6, ttl=0
|
||||
|
||||
// write addl RR
|
||||
code_domain(write_buffer, local); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, 1); // A
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
|
||||
put16bits(write_buffer, 4); // rdLength
|
||||
*write_buffer++ = 127;
|
||||
*write_buffer++ = 0;
|
||||
*write_buffer++ = 0;
|
||||
*write_buffer++ = 1;
|
||||
|
||||
uint32_t out_bytes = write_buffer - bufferBegin;
|
||||
llarp::LogDebug("Sending cname, ", out_bytes, " bytes");
|
||||
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
|
||||
request->sendto_hook(request->user, request->from,
|
||||
ManagedBuffer(llarp_buffer_t(buf, out_bytes)));
|
||||
}
|
||||
|
||||
void
|
||||
writesend_dnss_revresponse(std::string reverse,
|
||||
const dnsd_question_request *request)
|
||||
{
|
||||
char buf[BUFFER_SIZE] = {0};
|
||||
|
||||
char *write_buffer = buf;
|
||||
char *bufferBegin = buf;
|
||||
// build header
|
||||
put16bits(write_buffer, request->hdr.id);
|
||||
// response
|
||||
put16bits(write_buffer, request->hdr.fields() | (1 << 15) | (1 << 10));
|
||||
|
||||
put16bits(write_buffer, 1); // QD (number of questions)
|
||||
put16bits(write_buffer, 1); // AN (number of answers)
|
||||
put16bits(write_buffer, 0); // NS (number of auth RRs)
|
||||
put16bits(write_buffer, 0); // AR (number of Additional RRs)
|
||||
|
||||
// code question
|
||||
code_domain(write_buffer, request->question.name);
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
|
||||
// code answer
|
||||
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
put16bits(write_buffer, reverse.size() + 2); // rdLength
|
||||
code_domain(write_buffer, reverse);
|
||||
|
||||
uint32_t out_bytes = write_buffer - bufferBegin;
|
||||
llarp::LogDebug("Sending reverse: ", reverse, " ", out_bytes, " bytes");
|
||||
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
|
||||
request->sendto_hook(request->user, request->from,
|
||||
ManagedBuffer(llarp_buffer_t(buf, out_bytes)));
|
||||
}
|
||||
|
||||
// FIXME: we need an DNS answer not a sockaddr
|
||||
// otherwise ttl, type and class can't be relayed correctly
|
||||
void
|
||||
writesend_dnss_response(llarp::huint32_t *hostRes,
|
||||
const dnsd_question_request *request)
|
||||
{
|
||||
// llarp::Addr test(*from);
|
||||
// llarp::LogInfo("from ", test);
|
||||
if(!hostRes)
|
||||
{
|
||||
llarp::LogWarn("Failed to resolve ", request->question.name);
|
||||
write404_dnss_response(request);
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[BUFFER_SIZE] = {0};
|
||||
|
||||
char *write_buffer = buf;
|
||||
char *bufferBegin = buf;
|
||||
// build header
|
||||
put16bits(write_buffer, request->hdr.id);
|
||||
put16bits(write_buffer, request->hdr.fields() | (1 << 15));
|
||||
|
||||
put16bits(write_buffer, 1); // QD (number of questions)
|
||||
put16bits(write_buffer, 1); // AN (number of answers)
|
||||
put16bits(write_buffer, 0); // NS (number of auth RRs)
|
||||
put16bits(write_buffer, 0); // AR (number of Additional RRs)
|
||||
|
||||
// code question
|
||||
code_domain(write_buffer, request->question.name);
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
|
||||
// code answer
|
||||
llarp::LogDebug("Sending question name: ", request->question.name);
|
||||
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
|
||||
put16bits(write_buffer, 4); // rdLength
|
||||
// put32bits(write_buffer, xhtonl(*hostRes).n);
|
||||
put32bits(write_buffer, hostRes->h);
|
||||
|
||||
// has to be a string of 4 bytes
|
||||
/*
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)hostRes;
|
||||
unsigned char *ip = (unsigned char *)&sin->sin_addr.s_addr;
|
||||
|
||||
put16bits(write_buffer, 4); // rdLength
|
||||
llarp::LogDebug("Sending ip: ", std::to_string(ip[0]), '.',
|
||||
std::to_string(ip[1]), '.', std::to_string(ip[2]), '.',
|
||||
std::to_string(ip[3]));
|
||||
*write_buffer++ = ip[0];
|
||||
*write_buffer++ = ip[1];
|
||||
*write_buffer++ = ip[2];
|
||||
*write_buffer++ = ip[3];
|
||||
*/
|
||||
|
||||
uint32_t out_bytes = write_buffer - bufferBegin;
|
||||
llarp::LogDebug("Sending found, ", out_bytes, " bytes");
|
||||
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
|
||||
request->sendto_hook(request->user, request->from,
|
||||
ManagedBuffer(llarp_buffer_t(buf, out_bytes)));
|
||||
}
|
||||
|
||||
void
|
||||
writesend_dnss_mxresponse(uint16_t priority, std::string mx,
|
||||
const struct sockaddr *from,
|
||||
dnsd_question_request *request)
|
||||
{
|
||||
char buf[BUFFER_SIZE] = {0};
|
||||
|
||||
char *write_buffer = buf;
|
||||
char *bufferBegin = buf;
|
||||
// build header
|
||||
put16bits(write_buffer, request->hdr.id);
|
||||
put16bits(write_buffer, request->hdr.fields() | (1 << 15));
|
||||
|
||||
put16bits(write_buffer, 1); // QD (number of questions)
|
||||
put16bits(write_buffer, 1); // AN (number of answers)
|
||||
put16bits(write_buffer, 0); // NS (number of auth RRs)
|
||||
put16bits(write_buffer, 0); // AR (number of Additional RRs)
|
||||
|
||||
// code question
|
||||
code_domain(write_buffer, request->question.name);
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
|
||||
// code answer
|
||||
llarp::LogDebug("Sending question name: ", request->question.name);
|
||||
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
|
||||
put16bits(write_buffer, 2 + (mx.size() + 2)); // rdLength
|
||||
put16bits(write_buffer, priority); // priority
|
||||
code_domain(write_buffer, mx); //
|
||||
|
||||
uint32_t out_bytes = write_buffer - bufferBegin;
|
||||
llarp::LogDebug("Sending found, ", out_bytes, " bytes");
|
||||
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
|
||||
request->sendto_hook(request->user, from,
|
||||
ManagedBuffer(llarp_buffer_t(buf, out_bytes)));
|
||||
}
|
||||
|
||||
void
|
||||
writesend_dnss_txtresponse(std::string txt, const struct sockaddr *from,
|
||||
dnsd_question_request *request)
|
||||
{
|
||||
char buf[BUFFER_SIZE] = {0};
|
||||
|
||||
char *write_buffer = buf;
|
||||
char *bufferBegin = buf;
|
||||
// build header
|
||||
put16bits(write_buffer, request->hdr.id);
|
||||
put16bits(write_buffer, request->hdr.fields() | (1 << 15));
|
||||
|
||||
put16bits(write_buffer, 1); // QD (number of questions)
|
||||
put16bits(write_buffer, 1); // AN (number of answers)
|
||||
put16bits(write_buffer, 0); // NS (number of auth RRs)
|
||||
put16bits(write_buffer, 0); // AR (number of Additional RRs)
|
||||
|
||||
// code question
|
||||
code_domain(write_buffer, request->question.name);
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
|
||||
// code answer
|
||||
llarp::LogDebug("Sending question name: ", request->question.name);
|
||||
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
|
||||
put16bits(write_buffer, request->question.type);
|
||||
put16bits(write_buffer, request->question.qClass);
|
||||
put32bits(write_buffer, 1); // ttl
|
||||
|
||||
put16bits(write_buffer, txt.size() + 2); // rdLength
|
||||
*write_buffer = txt.size(); // write size
|
||||
write_buffer++;
|
||||
code_domain(write_buffer, txt); //
|
||||
|
||||
uint32_t out_bytes = write_buffer - bufferBegin;
|
||||
llarp::LogDebug("Sending found, ", out_bytes, " bytes");
|
||||
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
|
||||
request->sendto_hook(request->user, from,
|
||||
ManagedBuffer(llarp_buffer_t(buf, out_bytes)));
|
||||
}
|
||||
|
||||
void
|
||||
handle_dnsc_result(dnsc_answer_request *client_request)
|
||||
{
|
||||
auto *server_request = (dnsd_question_request *)client_request->user;
|
||||
if(!server_request)
|
||||
{
|
||||
llarp::LogError("Couldn't map client requser user to a server request");
|
||||
return;
|
||||
}
|
||||
|
||||
client_request->packet.header.id = server_request->hdr.id; // stomp ID
|
||||
std::vector< byte_t > test = packet2bytes(client_request->packet);
|
||||
// llarp::LogInfo("packet2bytes figures we should send ", test.size(), "
|
||||
// bytes");
|
||||
|
||||
server_request->sendto_hook(server_request->user, server_request->from,
|
||||
ManagedBuffer(llarp_buffer_t(test)));
|
||||
|
||||
llarp_host_resolved(client_request);
|
||||
return;
|
||||
|
||||
// llarp::LogDebug("handle_dnsc_result - client request question type",
|
||||
// std::to_string(client_request->question.type));
|
||||
|
||||
/*
|
||||
if(client_request->question.type == 12)
|
||||
{
|
||||
writesend_dnss_revresponse(client_request->revDNS, server_request->from,
|
||||
server_request);
|
||||
}
|
||||
else if(client_request->question.type == 15)
|
||||
{
|
||||
writesend_dnss_mxresponse(client_request->result.h, client_request->revDNS,
|
||||
server_request->from, server_request);
|
||||
}
|
||||
else if(client_request->question.type == 16)
|
||||
{
|
||||
llarp::LogInfo("Writing TXT ", client_request->revDNS);
|
||||
writesend_dnss_txtresponse(client_request->revDNS, server_request->from,
|
||||
server_request);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(client_request->question.type != 1)
|
||||
{
|
||||
llarp::LogInfo("Returning type ", client_request->question.type,
|
||||
" as standard");
|
||||
}
|
||||
llarp::huint32_t *useHostRes = nullptr;
|
||||
if(client_request->found)
|
||||
useHostRes = &client_request->result;
|
||||
writesend_dnss_response(useHostRes, server_request->from, server_request);
|
||||
}
|
||||
llarp_host_resolved(client_request);
|
||||
*/
|
||||
}
|
||||
|
||||
// our generic version
|
||||
void
|
||||
handle_recvfrom(llarp_buffer_t *buffer, dnsd_question_request *request)
|
||||
{
|
||||
const size_t HDR_OFFSET = 12;
|
||||
const char *p_buffer = (const char *)buffer->base;
|
||||
|
||||
int rcode = (buffer->base[3] & 0x0F);
|
||||
llarp::LogDebug("dnsd rcode ", rcode);
|
||||
|
||||
if(!decode_hdr(buffer, &request->hdr))
|
||||
{
|
||||
llarp::LogError("failed to decode dns header");
|
||||
return;
|
||||
}
|
||||
p_buffer += HDR_OFFSET;
|
||||
std::string m_qName = "";
|
||||
int length = *p_buffer++;
|
||||
while(length != 0)
|
||||
{
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
char c = *p_buffer++;
|
||||
m_qName.append(1, c);
|
||||
}
|
||||
length = *p_buffer++;
|
||||
if(length != 0)
|
||||
m_qName.append(1, '.');
|
||||
}
|
||||
request->question.name = m_qName;
|
||||
request->question.type = get16bits(p_buffer);
|
||||
request->question.qClass = get16bits(p_buffer);
|
||||
|
||||
llarp::LogDebug("qName ", request->question.name);
|
||||
llarp::LogDebug("qType ", request->question.type);
|
||||
llarp::LogDebug("qClass ", request->question.qClass);
|
||||
|
||||
/*
|
||||
llarp::Addr test(*request->from);
|
||||
llarp::LogInfo("DNS request from ", test);
|
||||
llarp::Addr test2(from);
|
||||
llarp::LogInfo("DNS request from ", test2);
|
||||
*/
|
||||
|
||||
// sockaddr *fromCopy = new sockaddr(*from); // make our own sockaddr that
|
||||
// won't get cleaned up
|
||||
if(!request)
|
||||
{
|
||||
llarp::LogError("request is not configured");
|
||||
return;
|
||||
}
|
||||
if(!request->context)
|
||||
{
|
||||
llarp::LogError("request context is not configured");
|
||||
return;
|
||||
}
|
||||
if(request->context->intercept)
|
||||
{
|
||||
// llarp::Addr test(*from);
|
||||
// llarp::LogInfo("from ", test);
|
||||
dnsd_query_hook_response *intercept =
|
||||
request->context->intercept(request->question.name, request);
|
||||
// if(!forward_dns_request(m_qName))
|
||||
if(intercept != nullptr)
|
||||
{
|
||||
llarp::LogDebug("hook returned a response");
|
||||
if(intercept->dontSendResponse)
|
||||
{
|
||||
llarp::LogDebug("HOOKED: Not sending a response");
|
||||
return;
|
||||
}
|
||||
if(intercept->dontLookUp && intercept->returnThis.h)
|
||||
{
|
||||
llarp::LogDebug("HOOKED: sending an immediate override");
|
||||
// told that hook will handle overrides
|
||||
writesend_dnss_response(&intercept->returnThis, request);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: check request and context's client
|
||||
if(!request->context)
|
||||
{
|
||||
llarp::LogError("dnsd request context was not a dnsd context");
|
||||
writesend_dnss_response(nullptr, request);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
struct dns_tracker *tracker = (struct dns_tracker *)request->context->tracker;
|
||||
if (!tracker)
|
||||
{
|
||||
llarp::LogError("dnsd request context tracker was not a dns_tracker");
|
||||
sockaddr *fromCopy = new sockaddr(*from);
|
||||
writesend_dnss_response(nullptr, fromCopy, request);
|
||||
return;
|
||||
}
|
||||
dnsd_context *dnsd = tracker->dnsd;
|
||||
if (!dnsd)
|
||||
{
|
||||
llarp::LogError("tracker dnsd was not a dnsd context");
|
||||
sockaddr *fromCopy = new sockaddr(*from);
|
||||
writesend_dnss_response(nullptr, fromCopy, request);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// delete fromCopy;
|
||||
// call DNSc
|
||||
if(request->llarp)
|
||||
{
|
||||
// make async request
|
||||
llarp_resolve_host(&request->context->client, m_qName.c_str(),
|
||||
&handle_dnsc_result, (void *)request,
|
||||
request->question.type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// make raw/sync request
|
||||
raw_resolve_host(&request->context->client, m_qName.c_str(),
|
||||
&handle_dnsc_result, (void *)request,
|
||||
request->question.type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *saddr, ManagedBuffer buf)
|
||||
{
|
||||
if(!dns_udp_tracker.dnsd)
|
||||
{
|
||||
llarp::LogError("No tracker set in dnsd context");
|
||||
return;
|
||||
}
|
||||
// create new request
|
||||
auto *llarp_dns_request = new dnsd_question_request;
|
||||
llarp_dns_request->context = dns_udp_tracker.dnsd; // set context
|
||||
llarp_dns_request->from =
|
||||
new sockaddr(*saddr); // make a copy of the sockaddr
|
||||
llarp_dns_request->user = (void *)udp;
|
||||
llarp_dns_request->llarp = true;
|
||||
llarp_dns_request->sendto_hook =
|
||||
&llarp_sendto_dns_hook_func; // set sock hook
|
||||
// llarp::LogInfo("Server request's UDP ", llarp_dns_request->user);
|
||||
handle_recvfrom(&buf.underlying, llarp_dns_request);
|
||||
}
|
||||
|
||||
void
|
||||
raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr,
|
||||
ManagedBuffer buffer)
|
||||
{
|
||||
if(!dns_udp_tracker.dnsd)
|
||||
{
|
||||
llarp::LogError("No tracker set in dnsd context");
|
||||
return;
|
||||
}
|
||||
auto *llarp_dns_request = new dnsd_question_request;
|
||||
llarp_dns_request->context = dns_udp_tracker.dnsd; // set context
|
||||
llarp_dns_request->from =
|
||||
new sockaddr(*saddr); // make a copy of the sockaddr
|
||||
llarp_dns_request->user = (void *)sockfd;
|
||||
llarp_dns_request->llarp = false;
|
||||
llarp_dns_request->sendto_hook = &raw_sendto_dns_hook_func;
|
||||
|
||||
handle_recvfrom(&buffer.underlying, llarp_dns_request);
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_dnsd_init(struct dnsd_context *const dnsd, llarp::Logic *const logic,
|
||||
struct llarp_ev_loop *const netloop,
|
||||
const llarp::Addr &dnsd_sockaddr,
|
||||
const llarp::Addr &dnsc_sockaddr)
|
||||
{
|
||||
// struct sockaddr_in bindaddr;
|
||||
/*
|
||||
llarp::Addr dnsd_addr;
|
||||
bool ifRes = GetIFAddr(std::string(dnsd_ifname), dnsd_addr, AF_INET);
|
||||
if (!ifRes)
|
||||
{
|
||||
llarp::LogError("Couldn't init dns server, can't resolve interface: ",
|
||||
dnsd_ifname); return false;
|
||||
}
|
||||
llarp::LogInfo("DNSd interface ip ", dnsd_addr);
|
||||
*/
|
||||
|
||||
/*
|
||||
bindaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // network byte
|
||||
bindaddr.sin_family = AF_INET;
|
||||
bindaddr.sin_port = htons(dnsd_port);
|
||||
*/
|
||||
|
||||
dnsd->udp.user = &dns_udp_tracker;
|
||||
dnsd->udp.recvfrom = &llarp_handle_dns_recvfrom;
|
||||
dnsd->udp.tick = nullptr;
|
||||
|
||||
dns_udp_tracker.dnsd = dnsd;
|
||||
|
||||
dnsd->tracker = &dns_udp_tracker; // register global tracker with context
|
||||
dnsd->intercept = nullptr; // set default intercepter
|
||||
|
||||
// set up fresh socket
|
||||
dnsd->client.udp = new llarp_udp_io;
|
||||
dnsd->client.udp->user = &dns_udp_tracker;
|
||||
dnsd->client.udp->recvfrom = &llarp_handle_dns_recvfrom;
|
||||
dnsd->client.udp->tick = nullptr;
|
||||
|
||||
// configure dns client
|
||||
// llarp::LogInfo("DNSd setting relay to ", dnsc_sockaddr);
|
||||
if(!llarp_dnsc_init(&dnsd->client, logic, netloop, dnsc_sockaddr))
|
||||
{
|
||||
llarp::LogError("Couldnt init dns client");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(netloop)
|
||||
{
|
||||
llarp::LogInfo("DNSd binding to ", dnsd_sockaddr);
|
||||
return llarp_ev_add_udp(netloop, &dnsd->udp,
|
||||
(const sockaddr *)dnsd_sockaddr)
|
||||
!= -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
#ifndef LLARP_DNSD_HPP
|
||||
#define LLARP_DNSD_HPP
|
||||
|
||||
#include <dns.hpp> // question and dnsc
|
||||
#include <dnsc.hpp>
|
||||
#include <ev/ev.h> // for sockaadr
|
||||
|
||||
#include <string>
|
||||
|
||||
//
|
||||
// Input structures/functions:
|
||||
//
|
||||
|
||||
// fwd declaration
|
||||
struct dnsd_context;
|
||||
|
||||
/// sendto hook functor
|
||||
using sendto_dns_hook_func = std::function< ssize_t(
|
||||
void *sock, const struct sockaddr *from, ManagedBuffer) >;
|
||||
// FIXME: llarp::Addr
|
||||
|
||||
/// DNS server query request
|
||||
struct dnsd_question_request
|
||||
{
|
||||
/// sock type
|
||||
void *user;
|
||||
// raw or llarp subsystem (is this used? does this matter?)
|
||||
bool llarp;
|
||||
/// request header
|
||||
dns_msg_header hdr;
|
||||
/// question being asked
|
||||
dns_msg_question question;
|
||||
// request source socket
|
||||
struct sockaddr *from; // FIXME: convert to llarp::Addr
|
||||
sendto_dns_hook_func sendto_hook; // sendto hook tbh
|
||||
// maybe a reference to dnsd_context incase of multiple
|
||||
dnsd_context *context; // or you can access it via user (udp)
|
||||
};
|
||||
|
||||
// FIXME: made better as a two way structure, collapse the request and response
|
||||
// together
|
||||
struct dnsd_query_hook_response
|
||||
{
|
||||
/// turn off communication
|
||||
bool dontSendResponse;
|
||||
/// turn off recursion
|
||||
bool dontLookUp;
|
||||
/// potential address
|
||||
llarp::huint32_t returnThis;
|
||||
};
|
||||
|
||||
/// builds and fires a request based based on llarp_udp_io udp event
|
||||
/// called by the llarp_handle_dns_recvfrom generic (dnsd/dnsc) handler in dns
|
||||
void
|
||||
llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *addr, ManagedBuffer buf);
|
||||
|
||||
//
|
||||
// output structures/functions:
|
||||
//
|
||||
// we may want to pass dnsd_question_request to these,
|
||||
// incase we need to send an error back up through the pipeline
|
||||
|
||||
// FIXME: just use the from in the request
|
||||
|
||||
/// NXDOMAIN not found
|
||||
void
|
||||
write404_dnss_response(const dnsd_question_request *request);
|
||||
|
||||
/// for hook functions to use
|
||||
void
|
||||
writecname_dnss_response(std::string cname,
|
||||
const dnsd_question_request *request);
|
||||
// FIXME: llarp::Addr
|
||||
|
||||
/// send an A record found response
|
||||
void
|
||||
writesend_dnss_response(llarp::huint32_t *hostRes,
|
||||
const dnsd_question_request *request);
|
||||
// FIXME: llarp::Addr
|
||||
|
||||
/// send an PTR record found response
|
||||
void
|
||||
writesend_dnss_revresponse(std::string reverse,
|
||||
const dnsd_question_request *request);
|
||||
// FIXME: llarp::Addr
|
||||
|
||||
//
|
||||
// setup/teardown functions/structure:
|
||||
//
|
||||
|
||||
/// intercept query hook functor
|
||||
using intercept_query_hook = std::function< dnsd_query_hook_response *(
|
||||
std::string name, const dnsd_question_request *request) >;
|
||||
// FIXME: llarp::Addr
|
||||
|
||||
/// DNS Server context
|
||||
struct dnsd_context
|
||||
{
|
||||
/// DNS daemon socket to listen on
|
||||
struct llarp_udp_io udp;
|
||||
/// udp tracker
|
||||
struct dns_tracker *tracker;
|
||||
/// upstream DNS client context to use
|
||||
dnsc_context client;
|
||||
/// custom data for intercept query hook (used for configuration of hook)
|
||||
void *user;
|
||||
/// hook function for intercepting dns requests
|
||||
intercept_query_hook intercept;
|
||||
};
|
||||
|
||||
/// initialize dns subsystem and bind socket
|
||||
/// returns true on bind success otherwise returns false
|
||||
bool
|
||||
llarp_dnsd_init(struct dnsd_context *const dnsd, llarp::Logic *const logic,
|
||||
struct llarp_ev_loop *const netloop,
|
||||
const llarp::Addr &dnsd_sockaddr,
|
||||
const llarp::Addr &dnsc_sockaddr);
|
||||
|
||||
/// shutdowns any events, and deallocates for this context
|
||||
bool
|
||||
llarp_dnsd_stop(struct dnsd_context *const dnsd);
|
||||
|
||||
#endif
|
@ -1,203 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <dns.hpp>
|
||||
#include <dnsc.hpp>
|
||||
#include <llarp.h> // for llarp_main_init
|
||||
#include <net/net.hpp> // for llarp::Addr
|
||||
#include <util/thread/logic.hpp> // for threadpool/llarp::Logic
|
||||
|
||||
struct DNSTest : public ::testing::Test
|
||||
{
|
||||
unsigned char buf[47] = {
|
||||
0x00, 0x01, // first short
|
||||
0x01, 0x00, 0x00, // combined fields
|
||||
0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // last 4 shorts
|
||||
// question (is 18 bytes long)
|
||||
0x04, // 4 letters
|
||||
0x6C, 0x6F, 0x6B, 0x69, // loki
|
||||
0x07, // 7 letters
|
||||
0x6E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, // network
|
||||
0x00, // end
|
||||
0x00, 0x01, // type (a 1/ptr 12)
|
||||
0x00, 0x01, // class (1 = internet)
|
||||
// 30th byte
|
||||
// Answer (is 16 bytes long)
|
||||
0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, // name, type, class
|
||||
0x00, 0x00, 0x08, 0x4b, // ttl 2123
|
||||
0x00, 0x04, // rdLen
|
||||
0x45, 0x10, 0xd1, 0x02, // an ip address
|
||||
// extra
|
||||
0x00 // null terminator (probably don't need this, just added it)
|
||||
};
|
||||
llarp_buffer_t buffer_t;
|
||||
|
||||
DNSTest()
|
||||
{
|
||||
this->buffer_t.base = (byte_t *)this->buf;
|
||||
this->buffer_t.cur = buffer_t.base;
|
||||
this->buffer_t.sz = 47;
|
||||
}
|
||||
|
||||
void
|
||||
SetUp()
|
||||
{
|
||||
llarp::SetLogLevel(
|
||||
llarp::eLogNone); // turn off logging to keep gtest output pretty
|
||||
/*
|
||||
const char *url = "loki.network";
|
||||
struct dns_query *packet = build_dns_packet((char *)url, 1, 1); // id 1,
|
||||
type 1 (A)
|
||||
|
||||
unsigned int length = packet->length;
|
||||
char *buffer = (char *)packet->request;
|
||||
char hex_buffer[length * 5 + 1];
|
||||
hex_buffer[length * 5] = 0;
|
||||
for(unsigned int j = 0; j < length; j++)
|
||||
sprintf(&hex_buffer[5 * j], "0x%02X,", ((const char *)buffer)[j]);
|
||||
printf("Generated [%u] bytes: [%s]\n", length, hex_buffer);
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
// test puts/gets
|
||||
// test code_domain / getDNSstring
|
||||
TEST_F(DNSTest, TestDecodeDNSstring)
|
||||
{
|
||||
char *buffer = (char *)this->buf;
|
||||
buffer += 12; // skip header
|
||||
uint32_t pos = 0;
|
||||
std::string res = getDNSstring(buffer, &pos);
|
||||
ASSERT_TRUE(res == "loki.network");
|
||||
}
|
||||
|
||||
TEST_F(DNSTest, TestCodeDomain)
|
||||
{
|
||||
char buffer[16];
|
||||
llarp::Zero(buffer, 16);
|
||||
char *write_buffer = buffer;
|
||||
std::string url = "bob.com";
|
||||
code_domain(write_buffer, url);
|
||||
|
||||
char hex_buffer[16 * 3 + 1];
|
||||
hex_buffer[16 * 3] = 0;
|
||||
for(unsigned int j = 0; j < 16; j++)
|
||||
sprintf(&hex_buffer[3 * j], "%02X ", ((const char *)buffer)[j]);
|
||||
// printf("first 16 [%s]", hex_buffer);
|
||||
|
||||
std::string expected_result =
|
||||
"03 62 6F 62 03 63 6F 6D 00 00 00 00 00 00 00 00 ";
|
||||
ASSERT_TRUE(hex_buffer == expected_result);
|
||||
}
|
||||
|
||||
// test decoders
|
||||
TEST_F(DNSTest, TestDecodeHdr)
|
||||
{
|
||||
dns_msg_header hdr;
|
||||
ASSERT_TRUE(decode_hdr(&this->buffer_t, &hdr));
|
||||
// rewind
|
||||
buffer_t.cur = buffer_t.base;
|
||||
/*
|
||||
printf("id[%d]", hdr->id);
|
||||
printf("qr[%d]", hdr->qr);
|
||||
printf("oc[%d]", hdr->opcode);
|
||||
printf("aa[%d]", hdr->aa);
|
||||
printf("tc[%d]", hdr->tc);
|
||||
printf("rd[%d]", hdr->rd);
|
||||
printf("ra[%d]", hdr->ra);
|
||||
printf("z [%d]", hdr->z);
|
||||
printf("ad[%d]", hdr->ad);
|
||||
printf("cd[%d]", hdr->cd);
|
||||
printf("rc[%d]", hdr->rcode);
|
||||
printf("qd[%d]", hdr->qdCount);
|
||||
printf("an[%d]", hdr->anCount);
|
||||
printf("ns[%d]", hdr->nsCount);
|
||||
printf("ar[%d]", hdr->arCount);
|
||||
*/
|
||||
ASSERT_TRUE(hdr.id == 1);
|
||||
ASSERT_TRUE(hdr.qr == 0);
|
||||
ASSERT_TRUE(hdr.opcode == 0);
|
||||
ASSERT_TRUE(hdr.aa == 0);
|
||||
ASSERT_TRUE(hdr.tc == 0);
|
||||
ASSERT_TRUE(hdr.rd == 0);
|
||||
ASSERT_TRUE(hdr.ra == 0);
|
||||
ASSERT_TRUE(hdr.z == 0);
|
||||
ASSERT_TRUE(hdr.ad == 0);
|
||||
ASSERT_TRUE(hdr.cd == 0);
|
||||
ASSERT_TRUE(hdr.rcode == 0);
|
||||
ASSERT_TRUE(hdr.qdCount == 1);
|
||||
ASSERT_TRUE(hdr.anCount == 1);
|
||||
ASSERT_TRUE(hdr.nsCount == 0);
|
||||
ASSERT_TRUE(hdr.arCount == 0);
|
||||
}
|
||||
|
||||
TEST_F(DNSTest, TestDecodeQuestion)
|
||||
{
|
||||
char *buffer = (char *)this->buf;
|
||||
buffer += 12; // skip header
|
||||
uint32_t pos = 0;
|
||||
dns_msg_question *question = decode_question(buffer, &pos);
|
||||
// printf("name[%s]", question->name.c_str());
|
||||
// printf("type[%d]", question->type);
|
||||
// printf("qClass[%d]", question->qClass);
|
||||
std::string url = "loki.network";
|
||||
ASSERT_TRUE(question->name == url);
|
||||
ASSERT_TRUE(question->type == 1);
|
||||
ASSERT_TRUE(question->qClass == 1);
|
||||
}
|
||||
|
||||
TEST_F(DNSTest, TestDecodeAnswer)
|
||||
{
|
||||
const char *const buffer = (const char *)this->buf;
|
||||
uint32_t pos = 12;
|
||||
std::string url = "loki.network";
|
||||
pos += url.length() + 2 + 4; // skip question (string + 2 shorts)
|
||||
|
||||
dns_msg_answer *answer = decode_answer(buffer, &pos);
|
||||
/*
|
||||
printf("type[%d]", answer->type);
|
||||
printf("aClass[%d]", answer->aClass);
|
||||
printf("ttl[%d]", answer->ttl);
|
||||
printf("rdLen[%d]", answer->rdLen);
|
||||
printf("[%hhu].[%hhu].[%hhu].[%hhu]", answer->rData[0], answer->rData[1],
|
||||
answer->rData[2], answer->rData[3]);
|
||||
*/
|
||||
ASSERT_TRUE(answer->name == url);
|
||||
ASSERT_TRUE(answer->type == 1);
|
||||
ASSERT_TRUE(answer->aClass == 1);
|
||||
ASSERT_TRUE(answer->ttl == 2123);
|
||||
ASSERT_TRUE(answer->rdLen == 4);
|
||||
ASSERT_TRUE(answer->rData[0] == 69);
|
||||
ASSERT_TRUE(answer->rData[1] == 16);
|
||||
ASSERT_TRUE(answer->rData[2] == 209);
|
||||
ASSERT_TRUE(answer->rData[3] == 2);
|
||||
}
|
||||
|
||||
/// UDP handling configuration
|
||||
struct llarp_udp_io_mock
|
||||
{
|
||||
/// set after added
|
||||
int fd;
|
||||
void *user;
|
||||
void *impl;
|
||||
struct llarp_ev_loop *parent;
|
||||
/// called every event loop tick after reads
|
||||
void (*tick)(struct llarp_udp_io *);
|
||||
// sockaddr * is the source
|
||||
void (*recvfrom)(struct llarp_udp_io *, const struct sockaddr *, const void *,
|
||||
ssize_t);
|
||||
};
|
||||
|
||||
// will have to mock udp and intercept the sendto call...
|
||||
// test llarp_handle_dns_recvfrom
|
||||
TEST_F(DNSTest, handleDNSrecvFrom)
|
||||
{
|
||||
llarp_udp_io_mock udp;
|
||||
sockaddr addr;
|
||||
std::array< byte_t, 16 > buffer;
|
||||
std::fill(buffer.begin(), buffer.end(), 0);
|
||||
// hdr->qr decides dnsc (1) or dnsd (0)
|
||||
llarp_handle_dns_recvfrom((llarp_udp_io *)&udp, &addr,
|
||||
ManagedBuffer(llarp_buffer_t(buffer)));
|
||||
// llarp_handle_dnsc_recvfrom
|
||||
// llarp_handle_dnsd_recvfrom
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <dnsd.hpp>
|
||||
|
||||
#include <llarp.h> // for llarp_main_init
|
||||
#include <net/net.hpp> // for llarp::Addr
|
||||
#include <util/thread/logic.hpp> // for threadpool/llarp::Logic
|
||||
|
||||
unsigned int g_length = 0;
|
||||
std::string g_result = "";
|
||||
|
||||
ssize_t
|
||||
test_sendto_dns_hook(__attribute__((unused)) void *sock,
|
||||
__attribute__((unused)) const struct sockaddr *from,
|
||||
ManagedBuffer buf)
|
||||
{
|
||||
char *hex_buffer = new char[buf.underlying.sz * 3 + 1];
|
||||
hex_buffer[buf.underlying.sz * 3] = 0;
|
||||
for(unsigned int j = 0; j < buf.underlying.sz; j++)
|
||||
sprintf(&hex_buffer[3 * j], "%02X ", ((char *)buf.underlying.base)[j]);
|
||||
// printf("Got [%zu] bytes: [%s]\n", length, hex_buffer);
|
||||
g_result = hex_buffer;
|
||||
g_length = buf.underlying.sz;
|
||||
delete[] hex_buffer;
|
||||
return buf.underlying.sz;
|
||||
}
|
||||
|
||||
struct llarpDNSdTest : public ::testing::Test
|
||||
{
|
||||
dnsd_question_request test_request;
|
||||
|
||||
llarpDNSdTest()
|
||||
{
|
||||
}
|
||||
void
|
||||
SetUp()
|
||||
{
|
||||
test_request.hdr.id = 0;
|
||||
test_request.llarp = true; // we don't care about raw atm
|
||||
test_request.from = nullptr;
|
||||
test_request.context = nullptr;
|
||||
test_request.sendto_hook = &test_sendto_dns_hook;
|
||||
test_request.question.name = "loki.network";
|
||||
test_request.question.type = 1;
|
||||
test_request.question.qClass = 1;
|
||||
g_result = ""; // reset test global
|
||||
g_length = 0;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(llarpDNSdTest, TestNxDomain)
|
||||
{
|
||||
write404_dnss_response(&test_request);
|
||||
ASSERT_TRUE(g_length == 55);
|
||||
std::string expected_output =
|
||||
"00 00 FFF03 00 01 00 01 00 00 00 00 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 "
|
||||
"6B 00 00 01 00 01 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 6B 00 00 01 00 01 "
|
||||
"00 00 00 01 00 01 00 ";
|
||||
// TODO: rewrite this test
|
||||
// ASSERT_TRUE(expected_output == g_result);
|
||||
}
|
||||
|
||||
TEST_F(llarpDNSdTest, TestAResponse)
|
||||
{
|
||||
llarp::huint32_t hostRes = {0};
|
||||
// sockaddr hostRes;
|
||||
// llarp::Zero(&hostRes, sizeof(sockaddr));
|
||||
writesend_dnss_response(&hostRes, &test_request);
|
||||
ASSERT_TRUE(g_length == 58);
|
||||
std::string expected_output =
|
||||
"00 00 FFF00 00 01 00 01 00 00 00 00 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 "
|
||||
"6B 00 00 01 00 01 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 6B 00 00 01 00 01 "
|
||||
"00 00 00 01 00 04 00 00 00 00 ";
|
||||
// TODO: rewrite this test
|
||||
// ASSERT_TRUE(expected_output == g_result);
|
||||
}
|
||||
|
||||
TEST_F(llarpDNSdTest, TestPTRResponse)
|
||||
{
|
||||
writesend_dnss_revresponse("loki.network", &test_request);
|
||||
ASSERT_TRUE(g_length == 68);
|
||||
std::string expected_output =
|
||||
"00 00 FFF00 00 01 00 01 00 00 00 00 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 "
|
||||
"6B 00 00 01 00 01 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 6B 00 00 01 00 01 "
|
||||
"00 00 00 01 00 0E 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 6B 00 ";
|
||||
// TODO: rewrite this test
|
||||
// ASSERT_TRUE(expected_output == g_result);
|
||||
}
|
||||
|
||||
TEST_F(llarpDNSdTest, TestCname)
|
||||
{
|
||||
writecname_dnss_response("test.cname", &test_request);
|
||||
ASSERT_TRUE(g_length == 122);
|
||||
std::string expected_output =
|
||||
"00 00 FFF00 00 01 00 01 00 01 00 01 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 "
|
||||
"6B 00 00 01 00 01 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 6B 00 00 05 00 01 "
|
||||
"00 00 00 01 00 0C 04 74 65 73 74 05 63 6E 61 6D 65 00 04 74 65 73 74 05 "
|
||||
"63 6E 61 6D 65 00 00 02 00 01 00 00 00 01 00 0A 03 6E 73 31 04 6C 6F 6B "
|
||||
"69 00 03 6E 73 31 04 6C 6F 6B 69 00 00 01 00 01 00 00 00 01 00 04 7F 00 "
|
||||
"00 01 ";
|
||||
// TODO: rewrite this test
|
||||
// ASSERT_TRUE(expected_output == g_result);
|
||||
}
|
Loading…
Reference in New Issue