lokinet/llarp/dns/name.cpp
Jeff 21930cf667
LNS (#1342)
* initial relay side lns

* fix typo

* add reserved names and refactor test for dns

* lns name decryption

* all wired up (allegedly)

* refact to use service::EncryptedName for LNS responses to include nonce with ciphertext

* fully rwemove tag_lookup_job

* replace lns cache with DecayingHashTable

* check for lns name validity against the following rules:

* not localhost.loki, loki.loki, or snode.loki

* if it contains no dash then max 32 characters long, not including the .loki tld (and also assuming a leading subdomain has been stripped)

* These are from general DNS requirements, and also enforced in
registrations:

* Must be all [A-Za-z0-9-]. (A-Z will be lower-cased by the RPC call).

* cannot start or end with a -

* max 63 characters long if it does contain a dash

* cannot contain -- in the third and fourth characters unless it starts with xn--

* handle timeout in name lookup job by calling the right handler with std::nullopt
2020-09-17 15:18:08 -04:00

141 lines
3.3 KiB
C++

#define __USE_MINGW_ANSI_STDIO 1
#include <dns/name.hpp>
#include <net/net.hpp>
#include <net/ip.hpp>
#include <util/str.hpp>
#include <algorithm>
#include <sstream>
namespace llarp
{
namespace dns
{
bool
DecodeName(llarp_buffer_t* buf, Name_t& name, bool trimTrailingDot)
{
if (buf->size_left() < 1)
return false;
std::stringstream ss;
size_t l;
do
{
l = *buf->cur;
buf->cur++;
if (l)
{
if (buf->size_left() < l)
return false;
ss << Name_t((const char*)buf->cur, l);
ss << ".";
}
buf->cur = buf->cur + l;
} while (l);
name = ss.str();
/// trim off last dot
if (trimTrailingDot)
name = name.substr(0, name.find_last_of('.'));
return true;
}
bool
EncodeName(llarp_buffer_t* buf, Name_t name)
{
std::stringstream ss;
if (name.size() && name[name.size() - 1] == '.')
ss << name.substr(0, name.size() - 1);
else
ss << name;
std::string part;
while (std::getline(ss, part, '.'))
{
size_t l = part.length();
if (l > 63)
return false;
*(buf->cur) = l;
buf->cur++;
if (buf->size_left() < l)
return false;
if (l)
{
memcpy(buf->cur, part.data(), l);
buf->cur += l;
}
else
break;
}
*buf->cur = 0;
buf->cur++;
return true;
}
bool
DecodePTR(Name_t name, huint128_t& ip)
{
bool isV6 = false;
auto pos = name.find(".in-addr.arpa");
if (pos == std::string::npos)
{
pos = name.find(".ip6.arpa");
isV6 = true;
}
if (pos == std::string::npos)
return false;
std::string sub = name.substr(0, pos + 1);
const auto numdots = std::count(sub.begin(), sub.end(), '.');
if (numdots == 4 && !isV6)
{
uint8_t a, b, c, d;
pos = sub.find('.');
d = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1);
pos = sub.find('.');
c = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1);
pos = sub.find('.');
b = atoi(sub.substr(0, pos).c_str());
sub = sub.substr(pos + 1);
pos = sub.find('.');
a = atoi(sub.substr(0, pos).c_str());
ip = net::ExpandV4(llarp::ipaddr_ipv4_bits(a, b, c, d));
return true;
}
if (numdots == 32 && isV6)
{
size_t idx = 0;
uint8_t lo, hi;
auto* ptr = (uint8_t*)&ip.h;
while (idx < 16)
{
pos = sub.find('.');
lo = (*sub.substr(0, pos).c_str()) - 'a';
sub = sub.substr(pos + 1);
pos = sub.find('.');
hi = (*sub.substr(0, pos).c_str()) - 'a';
sub = sub.substr(pos + 1);
ptr[idx] = lo | (hi << 4);
++idx;
}
return true;
}
return false;
}
bool
NameIsReserved(Name_t name)
{
const std::vector<std::string_view> reserved_names = {
"snode.loki"sv, "loki.loki"sv, "snode.loki."sv, "loki.loki."sv};
for (const auto& reserved : reserved_names)
{
if (ends_with(name, reserved))
return true;
}
return false;
}
} // namespace dns
} // namespace llarp