mirror of https://github.com/oxen-io/lokinet
commit
24986a682f
@ -0,0 +1,188 @@
|
||||
#include "dnsd.hpp" // for llarp_handle_dnsd_recvfrom, dnsc
|
||||
#include "logger.hpp"
|
||||
#include <string.h>
|
||||
|
||||
uint16_t
|
||||
get16bits(const char *&buffer) throw()
|
||||
{
|
||||
uint16_t value = static_cast< unsigned char >(buffer[0]);
|
||||
value = value << 8;
|
||||
value += static_cast< unsigned char >(buffer[1]);
|
||||
buffer += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
// uint32_t
|
||||
uint32_t
|
||||
get32bits(const char *&buffer) throw()
|
||||
{
|
||||
uint32_t value = uint32_t(
|
||||
(unsigned char)(buffer[0]) << 24 | (unsigned char)(buffer[1]) << 16
|
||||
| (unsigned char)(buffer[2]) << 8 | (unsigned char)(buffer[3]));
|
||||
buffer += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
dns_msg_header *
|
||||
decode_hdr(const char *buffer)
|
||||
{
|
||||
dns_msg_header *hdr = new dns_msg_header;
|
||||
hdr->id = get16bits(buffer);
|
||||
uint fields = get16bits(buffer);
|
||||
uint8_t lFields = (fields & 0x00FF) >> 0;
|
||||
uint8_t hFields = (fields & 0xFF00) >> 8;
|
||||
// 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;
|
||||
|
||||
hdr->ra = (lFields >> 7) & 0x1;
|
||||
//hdr->z = (lFields >> 6) & 0x1;
|
||||
//hdr->ad = (lFields >> 5) & 0x1;
|
||||
//hdr->cd = (lFields >> 4) & 0x1;
|
||||
hdr->rcode = lFields & 0xf;
|
||||
|
||||
hdr->qdCount = get16bits(buffer);
|
||||
hdr->anCount = get16bits(buffer);
|
||||
hdr->nsCount = get16bits(buffer);
|
||||
hdr->arCount = get16bits(buffer);
|
||||
return hdr;
|
||||
}
|
||||
|
||||
dns_msg_question *
|
||||
decode_question(const char *buffer)
|
||||
{
|
||||
dns_msg_question *question = new dns_msg_question;
|
||||
std::string m_qName = "";
|
||||
int length = *buffer++;
|
||||
// llarp::LogInfo("qNamLen", length);
|
||||
while(length != 0)
|
||||
{
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
char c = *buffer++;
|
||||
m_qName.append(1, c);
|
||||
}
|
||||
length = *buffer++;
|
||||
if(length != 0)
|
||||
m_qName.append(1, '.');
|
||||
}
|
||||
question->name = m_qName;
|
||||
question->type = get16bits(buffer);
|
||||
question->qClass = get16bits(buffer);
|
||||
return question;
|
||||
}
|
||||
|
||||
dns_msg_answer *
|
||||
decode_answer(const char *buffer)
|
||||
{
|
||||
dns_msg_answer *answer = new dns_msg_answer;
|
||||
answer->type = get16bits(buffer);
|
||||
//assert(answer->type < 259);
|
||||
if (answer->type > 259)
|
||||
{
|
||||
llarp::LogWarn("Answer type is off the charts");
|
||||
}
|
||||
answer->aClass = get16bits(buffer);
|
||||
answer->ttl = get32bits(buffer);
|
||||
answer->rdLen = get16bits(buffer);
|
||||
if (answer->rdLen == 4)
|
||||
{
|
||||
answer->rData = new uint8_t[answer->rdLen];
|
||||
memcpy(answer->rData, buffer, answer->rdLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogWarn("Unknown Type ", answer->type);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
void
|
||||
put16bits(char *&buffer, uint16_t value) throw()
|
||||
{
|
||||
buffer[0] = (value & 0xFF00) >> 8;
|
||||
buffer[1] = value & 0xFF;
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
void
|
||||
put32bits(char *&buffer, uint32_t value) throw()
|
||||
{
|
||||
buffer[0] = (value & 0xFF000000) >> 24;
|
||||
buffer[1] = (value & 0x00FF0000) >> 16;
|
||||
buffer[2] = (value & 0x0000FF00) >> 8;
|
||||
buffer[3] = (value & 0x000000FF) >> 0;
|
||||
buffer += 4;
|
||||
}
|
||||
|
||||
void
|
||||
code_domain(char *&buffer, const std::string &domain) throw()
|
||||
{
|
||||
int start(0), end; // indexes
|
||||
// llarp::LogInfo("domain [", domain, "]");
|
||||
while((end = domain.find('.', start)) != std::string::npos)
|
||||
{
|
||||
*buffer++ = end - start; // label length octet
|
||||
for(int 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(uint i = start; i < domain.size(); i++)
|
||||
{
|
||||
*buffer++ = domain[i]; // last label octets
|
||||
// llarp::LogInfo("Writing ", domain[i], " at ", i);
|
||||
}
|
||||
|
||||
*buffer++ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_handle_dns_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *saddr, const void *buf,
|
||||
ssize_t sz)
|
||||
{
|
||||
unsigned char *castBuf = (unsigned char *)buf;
|
||||
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
|
||||
dns_msg_header *hdr = decode_hdr((const char *)castBuf);
|
||||
// castBuf += 12;
|
||||
llarp::LogDebug("msg id ", hdr->id);
|
||||
llarp::LogDebug("msg qr ", (uint8_t)hdr->qr);
|
||||
if(hdr->qr)
|
||||
{
|
||||
llarp::LogDebug("handling as dnsc answer");
|
||||
llarp_handle_dnsc_recvfrom(udp, saddr, buf, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
llarp::LogDebug("handling as dnsd question");
|
||||
llarp_handle_dnsd_recvfrom(udp, saddr, buf, sz);
|
||||
}
|
||||
/*
|
||||
llarp::LogInfo("msg op ", hdr->opcode);
|
||||
llarp::LogInfo("msg rc ", hdr->rcode);
|
||||
|
||||
for(uint i = 0; i < hdr->qdCount; i++)
|
||||
{
|
||||
dns_msg_question *question = decode_question((const char*)castBuf);
|
||||
llarp::LogInfo("Read a question");
|
||||
castBuf += question->name.length() + 8;
|
||||
}
|
||||
|
||||
for(uint i = 0; i < hdr->anCount; i++)
|
||||
{
|
||||
dns_msg_answer *answer = decode_answer((const char*)castBuf);
|
||||
llarp::LogInfo("Read an answer");
|
||||
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
|
||||
}
|
||||
*/
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
#ifndef LIBLLARP_DNS_HPP
|
||||
#define LIBLLARP_DNS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <sys/types.h> // for uint & ssize_t
|
||||
|
||||
// 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 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;
|
||||
uint8_t *rData;
|
||||
};
|
||||
|
||||
uint16_t
|
||||
get16bits(const char *&buffer) throw();
|
||||
|
||||
uint32_t
|
||||
get32bits(const char *&buffer) throw();
|
||||
|
||||
dns_msg_header *
|
||||
decode_hdr(const char *buffer);
|
||||
|
||||
dns_msg_question *
|
||||
decode_question(const char *buffer);
|
||||
|
||||
dns_msg_answer *
|
||||
decode_answer(const char *buffer);
|
||||
|
||||
void
|
||||
put16bits(char *&buffer, uint16_t value) throw();
|
||||
|
||||
void
|
||||
put32bits(char *&buffer, uint32_t value) throw();
|
||||
|
||||
void
|
||||
code_domain(char *&buffer, const std::string &domain) throw();
|
||||
|
||||
void
|
||||
llarp_handle_dns_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *saddr, const void *buf,
|
||||
ssize_t sz);
|
||||
|
||||
#endif
|
@ -1,6 +1,61 @@
|
||||
#ifndef LIBLLARP_DNSC_HPP
|
||||
#define LIBLLARP_DNSC_HPP
|
||||
|
||||
#include <llarp/dns.h>
|
||||
#include <llarp/ev.h> // for sockaadr
|
||||
#include "dns.hpp" // get protocol structs
|
||||
|
||||
// internal, non-public functions
|
||||
// well dnsc init/stop are public...
|
||||
|
||||
struct dnsc_answer_request;
|
||||
|
||||
// should we pass by llarp::Addr
|
||||
// not as long as we're supporting raw
|
||||
typedef void (*dnsc_answer_hook_func)(dnsc_answer_request *request);
|
||||
|
||||
// FIXME: separate generic from llarp
|
||||
struct dnsc_answer_request
|
||||
{
|
||||
/// sock type
|
||||
void *sock; // pts to udp...
|
||||
/// customizable (used for hook (outer request))
|
||||
void *user;
|
||||
/// storage
|
||||
dns_msg_question question;
|
||||
/// hook
|
||||
dnsc_answer_hook_func resolved;
|
||||
/// result
|
||||
bool found;
|
||||
struct sockaddr result;
|
||||
// a reference to dnsc_context incase of multiple contexts
|
||||
struct dnsc_context *context;
|
||||
};
|
||||
|
||||
void
|
||||
llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *saddr, const void *buf,
|
||||
ssize_t sz);
|
||||
|
||||
void
|
||||
raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void *buf,
|
||||
ssize_t sz);
|
||||
|
||||
struct dnsc_context
|
||||
{
|
||||
/// Target: DNS server hostname/port to use
|
||||
// FIXME: ipv6 it
|
||||
sockaddr *server;
|
||||
// where to create the new sockets
|
||||
struct llarp_udp_io *udp;
|
||||
};
|
||||
|
||||
/// initialize dns subsystem and bind socket
|
||||
/// returns true on bind success otherwise returns false
|
||||
bool
|
||||
llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_udp_io *udp,
|
||||
const char *dnsc_hostname, uint16_t dnsc_port);
|
||||
|
||||
bool
|
||||
llarp_dnsc_stop(struct dnsc_context *dnsc);
|
||||
|
||||
#endif
|
||||
|
@ -1,40 +1,62 @@
|
||||
#ifndef LIBLLARP_DNSD_HPP
|
||||
#define LIBLLARP_DNSD_HPP
|
||||
|
||||
#include <string>
|
||||
#include "dns.hpp" // question and dnsc
|
||||
#include "dnsc.hpp"
|
||||
#include <llarp/ev.h> // for sockaadr
|
||||
#include <string>
|
||||
|
||||
struct dns_msg
|
||||
{
|
||||
uint id;
|
||||
uint qr;
|
||||
uint opcode;
|
||||
uint aa;
|
||||
uint tc;
|
||||
uint rd;
|
||||
uint ra;
|
||||
uint rcode;
|
||||
|
||||
uint qdCount;
|
||||
uint anCount;
|
||||
uint nsCount;
|
||||
uint arCount;
|
||||
};
|
||||
struct dnsd_context;
|
||||
|
||||
typedef ssize_t (*sendto_dns_hook_func)(void *sock, const struct sockaddr *from,
|
||||
const void *buffer, size_t length);
|
||||
|
||||
struct dns_request
|
||||
struct dnsd_question_request
|
||||
{
|
||||
/// sock type
|
||||
void *user;
|
||||
// raw or llarp subsystem
|
||||
bool llarp;
|
||||
/// request id
|
||||
int id;
|
||||
std::string m_qName;
|
||||
uint m_qType;
|
||||
uint m_qClass;
|
||||
/// question being asked
|
||||
dns_msg_question question;
|
||||
// request source socket
|
||||
struct sockaddr *from;
|
||||
sendto_dns_hook_func hook; // sendto hook tbh
|
||||
// maybe a reference to dnsd_context incase of multiple
|
||||
dnsd_context *context; // or you can access it via user (udp)
|
||||
};
|
||||
|
||||
// we could have passed in the source sockaddr in case you wanted to
|
||||
// handle the response yourself
|
||||
typedef sockaddr *(*intercept_query_hook)(std::string name);
|
||||
|
||||
struct dnsd_context
|
||||
{
|
||||
/// DNS daemon socket to listen on
|
||||
struct llarp_udp_io udp;
|
||||
dnsc_context client;
|
||||
/// custom data for intercept query hook
|
||||
void *user;
|
||||
/// hook function for intercepting dns requests
|
||||
intercept_query_hook intercept;
|
||||
};
|
||||
|
||||
void
|
||||
llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp,
|
||||
const struct sockaddr *paddr, const void *buf,
|
||||
ssize_t sz);
|
||||
|
||||
/// initialize dns subsystem and bind socket
|
||||
/// returns true on bind success otherwise returns false
|
||||
bool
|
||||
llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_ev_loop *netloop,
|
||||
const char *dnsd_ifname, uint16_t dnsd_port,
|
||||
const char *dnsc_hostname, uint16_t dnsc_port);
|
||||
|
||||
bool
|
||||
llarp_dnsd_stop(struct dnsd_context *dnsd);
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue