lokinet/test/test_llarp_dns.cpp

204 lines
6.2 KiB
C++

#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/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
}