From ca06f1dded716a2d207abc47dd3d53d91355f003 Mon Sep 17 00:00:00 2001 From: Ryan Tharp Date: Sat, 21 Jul 2018 20:34:28 -0700 Subject: [PATCH] refactor clean up (pass 1) --- include/llarp/dns.h | 170 ++-------------- llarp/dns.cpp | 187 ++++++++++++++++++ llarp/dns.hpp | 75 ++++++++ llarp/dnsc.cpp | 460 +++++++++++++++++++++----------------------- llarp/dnsc.hpp | 57 +++++- llarp/dnsd.cpp | 216 +++++---------------- llarp/dnsd.hpp | 47 ++++- 7 files changed, 636 insertions(+), 576 deletions(-) create mode 100644 llarp/dns.cpp create mode 100644 llarp/dns.hpp diff --git a/include/llarp/dns.h b/include/llarp/dns.h index 0f2653313..91c793201 100644 --- a/include/llarp/dns.h +++ b/include/llarp/dns.h @@ -1,8 +1,9 @@ #ifndef LLARP_DNS_H_ #define LLARP_DNS_H_ -#include +#include // for sockaadr #include // for uint & ssize_t +#include // for udp DNS tracker /** * dns.h @@ -10,53 +11,16 @@ * dns client/server */ -#include -typedef std::mutex mtx_t; -typedef std::lock_guard< mtx_t > lock_t; - -#include -struct dns_msg_header -{ - 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 dns_msg_question -{ - std::string name; - uint type; - uint qClass; -}; - -struct dns_msg_answer -{ - std::string name; - uint type; - uint aClass; - u_int32_t ttl; - uint rdLen; - uint rData; -}; +//#include +//typedef std::mutex mtx_t; +//typedef std::lock_guard< mtx_t > lock_t; // fwd declr -struct dns_query; +//struct dns_query; struct dnsc_context; struct dnsd_context; -struct dns_request; -struct dns_client_request; - -typedef bool (*intercept_query_hook)(struct dnsc_context *, const dns_query *); +//struct dnsd_question_request; +struct dnsc_answer_request; // dnsc can work over any UDP socket // however we can't ignore udp->user @@ -64,128 +28,26 @@ typedef bool (*intercept_query_hook)(struct dnsc_context *, const dns_query *); // bottom line is we can't use udp->user // so we'll need to track all incoming and outgoing requests -#include - struct dns_tracker { - uint c_responses; + //uint c_responses; uint c_requests; - std::map< uint, dns_client_request * > client_request; + std::map< uint, dnsc_answer_request * > client_request; dnsd_context *dnsd; - std::map< uint, dns_request * > daemon_request; + //std::map< uint, dnsd_question_request * > daemon_request; }; -struct dnsc_context -{ - /// DNS server hostname to use - // char *server; - /// DNS server port to use - // uint port; - /// Target: DNS server hostname/port to use - // FIXME: ipv6 it - sockaddr *server; - // where to create the new sockets - // struct llarp_ev_loop *netloop; - // FIXME: UDP socket pooling (or maybe at the libev level) - struct llarp_udp_io *udp; -}; - -struct dnsd_context -{ - /// DNS daemon port 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; -}; - -/// 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); - -bool -llarp_dnsc_unbind(struct dns_client_request *request); - -bool -llarp_dnsc_bind(struct llarp_udp_io *udp, struct dns_client_request *request); - -/// initialize dns subsystem and bind socket -/// returns true on bind success otherwise returns false -bool -llarp_dnsd_init(struct dnsd_context *dns, struct llarp_ev_loop *netloop, - const char *dnsd_ifname, uint16_t dnsd_port, - const char *dnsc_hostname, uint16_t dnsc_port); - -#define DNC_BUF_SIZE 512 - -struct dns_query -{ - uint16_t length; - char *url; - unsigned char request[DNC_BUF_SIZE]; - uint16_t reqType; -}; - -struct dns_client_request; - // should we pass by llarp::Addr // not as long as we're supporting raw -typedef void (*resolve_dns_hook_func)(dns_client_request *request); - -// FIXME: separate generic from llarp -struct dns_client_request -{ - /// sock type - void *sock; // pts to udp... - /// customizeable (used for outer request) - void *user; - /// storage - dns_query query; - /// hook - resolve_dns_hook_func resolved; - /// result - bool found; - struct sockaddr result; - /// Source: UDP port to use - // FIXME: separate socket for now - struct llarp_udp_io udp; - // maybe a link to dnsc_context -}; - -bool -llarp_dnsc_bind(struct llarp_ev_loop *netloop, - struct dns_client_request *request); +typedef void (*dnsc_answer_hook_func)(dnsc_answer_request *request); struct sockaddr * -resolveHost(const char *url); +raw_resolve_host(const char *url); + bool llarp_resolve_host(struct dnsc_context *dns, const char *url, - resolve_dns_hook_func resolved, void *user); -void -llarp_host_resolved(dns_client_request *request); - -void -llarp_handle_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *paddr, - const void *buf, ssize_t sz); - -void -llarp_handle_dns_recvfrom(struct llarp_udp_io *udp, - const struct sockaddr *saddr, const void *buf, - ssize_t sz); - -void -llarp_handle_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *saddr, - const void *buf, ssize_t sz); - + dnsc_answer_hook_func resolved, void *user); void -raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void *buf, - ssize_t sz); +llarp_host_resolved(dnsc_answer_request *request); #endif diff --git a/llarp/dns.cpp b/llarp/dns.cpp new file mode 100644 index 000000000..72eee094a --- /dev/null +++ b/llarp/dns.cpp @@ -0,0 +1,187 @@ +#include "dnsd.hpp" // for llarp_handle_dnsd_recvfrom, dnsc +#include "logger.hpp" + +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(int 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::LogInfo("msg id ", hdr->id); + llarp::LogInfo("msg qr ", (uint8_t)hdr->qr); + if(hdr->qr) + { + llarp::LogInfo("handling as dnsc answer"); + llarp_handle_dnsc_recvfrom(udp, saddr, buf, sz); + } + else + { + llarp::LogInfo("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; + } + */ +} diff --git a/llarp/dns.hpp b/llarp/dns.hpp new file mode 100644 index 000000000..cc3694f52 --- /dev/null +++ b/llarp/dns.hpp @@ -0,0 +1,75 @@ +#ifndef LIBLLARP_DNS_HPP +#define LIBLLARP_DNS_HPP + +#include +#include // 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 diff --git a/llarp/dnsc.cpp b/llarp/dnsc.cpp index 7755d6fd2..6457f67f6 100644 --- a/llarp/dnsc.cpp +++ b/llarp/dnsc.cpp @@ -1,6 +1,6 @@ -// why dnsd? what do you need from that? +#include "dnsc.hpp" +#include #include "buffer.hpp" -#include "dnsd.hpp" #include /* getaddrinfo, getnameinfo */ #include /* exit */ @@ -20,14 +20,80 @@ #define SERVER "8.8.8.8" #define PORT 53 -mtx_t m_dnsc_Mutex; -mtx_t m_dnsc2_Mutex; +#define DNC_BUF_SIZE 512 +// a question to be asked remotely +// header, question +struct dns_query +{ + uint16_t length; + //char *url; + unsigned char request[DNC_BUF_SIZE]; + //uint16_t reqType; +}; + +struct dns_query* +build_dns_packet(char *url, uint16_t id, uint16_t reqType) +{ + dns_query *dnsQuery = new dns_query; + dnsQuery->length = 12; + // ID + // buffer[0] = (value & 0xFF00) >> 8; + // buffer[1] = value & 0xFF; + llarp::LogInfo("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(NULL, "."); + } + + 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; +} struct sockaddr * -resolveHost(const char *url) +raw_resolve_host(const char *url) { - char *sUrl = strdup(url); - struct dns_query dnsQuery; + //char *sUrl = strdup(url); + //struct dns_query dnsQuery; + dns_query *dns_packet = build_dns_packet((char *)url, 0xDB42, 1); + + /* dnsQuery.length = 12; dnsQuery.url = sUrl; dnsQuery.reqType = 0x01; @@ -45,12 +111,13 @@ resolveHost(const char *url) dnsQuery.request[9] = 0x00; dnsQuery.request[10] = 0x00; dnsQuery.request[11] = 0x00; - + */ + char *word; unsigned int i; llarp::LogDebug("Asking DNS server ", SERVER, " about ", url); // dnsQuery.reqType = 0x01; - + /* word = strtok(sUrl, "."); while(word) { @@ -71,7 +138,8 @@ resolveHost(const char *url) dnsQuery.request[dnsQuery.length++] = 0x00; // 0x0001 - Query is class IN (Internet address) dnsQuery.request[dnsQuery.length++] = 0x01; - + */ + struct sockaddr_in addr; // int socket; ssize_t ret; @@ -109,8 +177,9 @@ resolveHost(const char *url) size = sizeof(addr); // hexdump("sending packet", &dnsQuery.request, dnsQuery.length); - ret = sendto(sockfd, dnsQuery.request, dnsQuery.length, 0, + ret = sendto(sockfd, dns_packet->request, dns_packet->length, 0, (struct sockaddr *)&addr, size); + delete dns_packet; if(ret < 0) { llarp::LogWarn("Error Sending Request"); @@ -148,7 +217,8 @@ resolveHost(const char *url) llarp::LogDebug("name server resource record count: %u\n", NSCOUNT); ARCOUNT = (uint16_t)buffer[10] * 0x100 + buffer[11]; llarp::LogDebug("additional records count: %u\n", ARCOUNT); - + + /* llarp::LogDebug("query type: %u\n", dnsQuery.reqType); QCLASS = (uint16_t)dnsQuery.request[dnsQuery.length - 2] * 0x100 + dnsQuery.request[dnsQuery.length - 1]; @@ -165,6 +235,7 @@ resolveHost(const char *url) llarp::LogDebug("bytes in answer: %u\n", RDLENGTH); MSGID = (uint16_t)buffer[0] * 0x100 + buffer[1]; llarp::LogDebug("answer msg id: %u\n", MSGID); + */ if(rcode == 2) { @@ -176,15 +247,15 @@ resolveHost(const char *url) } else if(rcode == 3) { - llarp::LogWarn("nameserver %s returned NXDOMAIN for %s:\n", SERVER, - dnsQuery.url); + llarp::LogWarn("nameserver %s returned NXDOMAIN for ", SERVER); llarp::LogWarn( " the domain name referenced in the query does not exist\n"); return nullptr; } /* search for and print IPv4 addresses */ - if(dnsQuery.reqType == 0x01) + //if(dnsQuery.reqType == 0x01) + if (1) { llarp::LogDebug("DNS server's answer is: (type#=%u):", ATYPE); // printf("IPv4 address(es) for %s:\n", dnsQuery.url); @@ -224,11 +295,11 @@ resolveHost(const char *url) } void -llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, +llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *saddr, const void *buf, ssize_t sz) { - lock_t lock(m_dnsc_Mutex); + //lock_t lock(m_dnsc_Mutex); // llarp::LogInfo("got a response, udp user is ", udp->user); unsigned char *castBuf = (unsigned char *)buf; @@ -239,12 +310,12 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, // if we sent this out, then there's an id struct dns_tracker *tracker = (struct dns_tracker *)udp->user; - struct dns_client_request *request = tracker->client_request[hdr->id]; + struct dnsc_answer_request *request = tracker->client_request[hdr->id]; if(!request) { llarp::LogError( - "User data to DNS Client response not a dns_client_request"); + "User data to DNS Client response not a dnsc_answer_request"); // we can't call back the hook return; } @@ -261,7 +332,7 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, // 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 @@ -272,36 +343,24 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, uint32_t TTL; // The number of seconds the results can be cached uint16_t RDLENGTH; // The length of the RDATA field uint16_t MSGID; - int rcode; - int length; + */ + uint8_t rcode; + //int length; - struct dns_query *dnsQuery = &request->query; + //struct dns_query *dnsQuery = &request->query; - rcode = (buffer[3] & 0x0F); - llarp::LogInfo("dnsc rcode ", rcode); + //rcode = (buffer[3] & 0x0F); + //llarp::LogInfo("dnsc rcode ", rcode); dns_msg_header *msg = decode_hdr((const char *)castBuf); castBuf += 12; llarp::LogInfo("msg id ", msg->id); - llarp::LogInfo("msg qr ", msg->qr); - llarp::LogInfo("msg op ", msg->opcode); - llarp::LogInfo("msg rc ", msg->rcode); - - // tempBuf[0] = buffer[4]; - // tempBuf[1] = buffer[5]; - // tempBuf[2] = '\0'; - - // printf("%0x %0x %0x %0x\n", buffer[4], buffer[5], tempBuf[0], tempBuf[1]); - - // QDCOUNT = (uint16_t) strtol(tempBuf, NULL, 16); - QDCOUNT = (uint16_t)buffer[4] * 0x100 + buffer[5]; - llarp::LogInfo("entries in question section: ", QDCOUNT); - ANCOUNT = (uint16_t)buffer[6] * 0x100 + buffer[7]; - llarp::LogInfo("records in answer section: ", ANCOUNT); - NSCOUNT = (uint16_t)buffer[8] * 0x100 + buffer[9]; - llarp::LogInfo("name server resource record count: ", NSCOUNT); - ARCOUNT = (uint16_t)buffer[10] * 0x100 + buffer[11]; - llarp::LogInfo("additional records count: ", ARCOUNT); + uint8_t qr = msg->qr; + llarp::LogInfo("msg qr ", qr); + uint8_t opcode = msg->opcode; + llarp::LogInfo("msg op ", opcode); + rcode = msg->rcode; + llarp::LogInfo("msg rc ", rcode); llarp::LogInfo("msg qdc ", msg->qdCount); llarp::LogInfo("msg anc ", msg->anCount); @@ -309,18 +368,48 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, llarp::LogInfo("msg arc ", msg->arCount); // we may need to parse question first - + + /* dns_msg_question *question = decode_question((const char *)castBuf); llarp::LogInfo("que name ", question->name); castBuf += question->name.length() + 8; dns_msg_answer *answer = decode_answer((const char *)castBuf); castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen; + */ + + // FIXME: only handling one atm + dns_msg_question *question = nullptr; + for(uint i = 0; i < hdr->qdCount; i++) + { + question = decode_question((const char*)castBuf); + llarp::LogInfo("Read a question"); + castBuf += question->name.length() + 8; + } + + // FIXME: only handling one atm + dns_msg_answer *answer = nullptr; + for(uint i = 0; i < hdr->anCount; i++) + { + answer = decode_answer((const char*)castBuf); + llarp::LogInfo("Read an answer"); + castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen; + } + // handle authority records (usually no answers with these, so we'll just stomp) + // usually NS records tho + for(uint i = 0; i < hdr->nsCount; i++) + { + answer = decode_answer((const char*)castBuf); + llarp::LogInfo("Read an authority"); + castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen; + } + // 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); @@ -339,7 +428,15 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, MSGID = (uint16_t)buffer[0] * 0x100 + buffer[1]; // llarp::LogDebug("answer msg id: %u\n", MSGID); + */ + if(answer == nullptr) + { + llarp::LogWarn("nameserver ", SERVER, " didnt return any answers:"); + request->resolved(request); + return; + } + llarp::LogInfo("ans class ", answer->aClass); llarp::LogInfo("ans type ", answer->type); llarp::LogInfo("ans ttl ", answer->ttl); @@ -364,7 +461,7 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, else if(rcode == 3) { llarp::LogWarn("nameserver ", SERVER, - " returned NXDOMAIN for: ", dnsQuery->url); + " returned NXDOMAIN for: ", request->question.name); llarp::LogWarn(" the domain name referenced in the query does not exist"); request->resolved(request); return; @@ -373,187 +470,100 @@ llarp_handle_dnsclient_recvfrom(struct llarp_udp_io *udp, int ip = 0; /* search for and print IPv4 addresses */ - if(dnsQuery->reqType == 0x01) + //if(dnsQuery->reqType == 0x01) + if(request->question.type == 1) { - llarp::LogInfo("DNS server's answer is: (type#=", ATYPE, "):"); - llarp::LogInfo("IPv4 address(es) for ", dnsQuery->url, ":"); - for(unsigned int i = 0; i < sz; i++) + //llarp::LogInfo("DNS server's answer is: (type#=", ATYPE, "):"); + llarp::LogInfo("IPv4 address(es) for ", request->question.name, ":"); + + if (answer->rdLen == 4) { - if(buffer[i] == 0xC0 && buffer[i + 3] == 0x01) - { - ip++; - i += 12; /* ! += buf[i+1]; */ - // llarp::LogInfo(" %u.%u.%u.%u\n", buffer[i], buffer[i+1], buffer[i+2], - // buffer[i+3]); - - /* - struct sockaddr *g_addr = new sockaddr; - g_addr->sa_family = AF_INET; - g_addr->sa_len = sizeof(in_addr); - struct in_addr *addr = &((struct sockaddr_in *)g_addr)->sin_addr; - */ - - unsigned char *ip; - - // have ip point to s_addr - request->result.sa_family = AF_INET; - request->result.sa_len = sizeof(in_addr); - struct in_addr *addr = - &((struct sockaddr_in *)&request->result)->sin_addr; - - // ip = (unsigned char *) &request->result.sa_data; - ip = (unsigned char *)&(addr->s_addr); - - ip[0] = buffer[i + 0]; - ip[1] = buffer[i + 1]; - ip[2] = buffer[i + 2]; - ip[3] = buffer[i + 3]; - llarp::Addr test(request->result); - llarp::LogInfo(test); - - // return g_addr; - // request->result = g_addr; - request->found = true; - request->resolved(request); - return; - } + request->result.sa_family = AF_INET; + request->result.sa_len = sizeof(in_addr); + 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]; + + llarp::Addr test(request->result); + llarp::LogInfo(test); + request->found = true; + request->resolved(request); + return; } if(!ip) { - llarp::LogWarn(" No IPv4 address found in the DNS response!"); + llarp::LogWarn(" No IPv4 address found in the DNS answer!"); request->resolved(request); return; } } } -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::LogInfo("msg id ", hdr->id); - llarp::LogInfo("msg qr ", hdr->qr); - if(hdr->qr) - { - llarp_handle_dnsclient_recvfrom(udp, saddr, buf, sz); - } - else - { - llarp_handle_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; - } - */ -} - -void -build_dns_query(struct dns_query *dnsQuery, uint id) -{ - dnsQuery->length = 12; - dnsQuery->reqType = 0x01; - // ID - // buffer[0] = (value & 0xFF00) >> 8; - // buffer[1] = value & 0xFF; - llarp::LogInfo("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(dnsQuery->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(NULL, "."); - } - - 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++] = dnsQuery->reqType; - dnsQuery->request[dnsQuery->length++] = - 0x00; // 0x0001 - Query is class IN (Internet address) - dnsQuery->request[dnsQuery->length++] = 0x01; -} - bool llarp_resolve_host(struct dnsc_context *dnsc, const char *url, - resolve_dns_hook_func resolved, void *user) + dnsc_answer_hook_func resolved, void *user) { - dns_client_request *request = new dns_client_request; - request->sock = (void *)&request->udp; - request->user = user; - // configure query - request->query.url = strdup(url); - request->resolved = resolved; - request->found = false; - - // request address holds through the packet recv - // request->udp.user = request; - - // finish setting up our query - struct dns_query *dnsQuery = &request->query; + dnsc_answer_request *request = new dnsc_answer_request; + request->sock = (void *)&dnsc->udp; + request->user = user; + request->resolved = resolved; + request->found = false; + request->context = dnsc; + + char *sUrl = strdup(url); + request->question.name = sUrl; + request->question.type = 1; + request->question.qClass = 1; + + // register request with udp response tracker dns_tracker *tracker = (dns_tracker *)dnsc->udp->user; - build_dns_query(dnsQuery, ++tracker->c_requests); - // build a socket per request because we're multithreaded and will have many - // inflight /* - if (!llarp_dnsc_bind(dnsc->netloop, request)) - { - llarp::LogWarn("Error binding"); - return false; - } + 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); */ - tracker->client_request[tracker->c_requests] = request; - - ssize_t ret = llarp_ev_udp_sendto(dnsc->udp, dnsc->server, dnsQuery->request, - dnsQuery->length); + + uint16_t id = ++tracker->c_requests; + tracker->client_request[id] = request; + //llarp::LogInfo("Sending request #", tracker->c_requests, " ", length, " bytes"); + + dns_query *dns_packet = build_dns_packet((char *)url, id, 1); + //ssize_t ret = llarp_ev_udp_sendto(dnsc->udp, dnsc->server, bytes, length); + ssize_t ret = llarp_ev_udp_sendto(dnsc->udp, dnsc->server, dns_packet->request, dns_packet->length); + delete dns_packet; if(ret < 0) { llarp::LogWarn("Error Sending Request"); @@ -564,42 +574,11 @@ llarp_resolve_host(struct dnsc_context *dnsc, const char *url, } void -llarp_host_resolved(dns_client_request *request) +llarp_host_resolved(dnsc_answer_request *request) { delete request; } -bool -llarp_dnsc_bind(struct llarp_ev_loop *netloop, - struct dns_client_request *request) -{ - lock_t lock(m_dnsc2_Mutex); - // just grab a random open port - struct sockaddr_in srcaddr; - srcaddr.sin_addr.s_addr = inet_addr("0.0.0.0"); - srcaddr.sin_family = AF_INET; - // we'll need to make sure the port is >1024 if not root - // llarp::LogInfo("outgoing port check ", ntohs(srcaddr.sin_port)); - if(ntohs(srcaddr.sin_port) < 1024) - srcaddr.sin_port = htons(ntohs(srcaddr.sin_port) + 1024); - - request->udp.user = request; - request->udp.recvfrom = &llarp_handle_dns_recvfrom; - request->udp.tick = nullptr; - - // create new listener for this request - return llarp_ev_add_udp(netloop, &request->udp, (const sockaddr *)&srcaddr) - != -1; -} - -// FIXME: drop the bool -bool -llarp_dnsc_unbind(struct dns_client_request *request) -{ - llarp_ev_close_udp(&request->udp); // stop listening - return true; -} - bool llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_udp_io *udp, const char *dnsc_hostname, uint16_t dnsc_port) @@ -616,7 +595,6 @@ llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_udp_io *udp, bool llarp_dnsc_stop(struct dnsc_context *dnsc) { - // llarp_ev_close_udp(&dnsc->udp); // stop listening delete(sockaddr_in *)dnsc->server; // deallocation return true; } diff --git a/llarp/dnsc.hpp b/llarp/dnsc.hpp index 94c010f19..134c1de8e 100644 --- a/llarp/dnsc.hpp +++ b/llarp/dnsc.hpp @@ -1,6 +1,61 @@ #ifndef LIBLLARP_DNSC_HPP #define LIBLLARP_DNSC_HPP -#include +#include // 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 diff --git a/llarp/dnsd.cpp b/llarp/dnsd.cpp index bdb0d52e8..6fb19b49d 100644 --- a/llarp/dnsd.cpp +++ b/llarp/dnsd.cpp @@ -1,139 +1,10 @@ #include "dnsd.hpp" +#include #include #include "ev.hpp" #include "logger.hpp" #include "net.hpp" -mtx_t m_dnsd_Mutex; -mtx_t m_dnsd2_Mutex; -mtx_t m_dnsd3_Mutex; - -int -get16bits(const char *&buffer) throw() -{ - int 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; -} - -void -put16bits(char *&buffer, uint value) throw() -{ - buffer[0] = (value & 0xFF00) >> 8; - buffer[1] = value & 0xFF; - buffer += 2; -} - -void -put32bits(char *&buffer, unsigned long value) throw() -{ - buffer[0] = (value & 0xFF000000) >> 24; - buffer[1] = (value & 0x00FF0000) >> 16; - buffer[2] = (value & 0x0000FF00) >> 8; - buffer[3] = (value & 0x000000FF) >> 0; - buffer += 4; -} - -dns_msg_header * -decode_hdr(const char *buffer) -{ - dns_msg_header *hdr = new dns_msg_header; - hdr->id = get16bits(buffer); - uint fields = get16bits(buffer); - // hdr->qr = fields & 0x8000; - hdr->qr = (fields >> 7) & 0x1; - hdr->opcode = fields & 0x7800; - hdr->aa = fields & 0x0400; - hdr->tc = fields & 0x0200; - hdr->rd = fields & 0x0100; - - hdr->ra = fields & 0x8000; - // z, ad, cd - hdr->rcode = (buffer[3] & 0x0F); - 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); - answer->aClass = get16bits(buffer); - answer->ttl = get32bits(buffer); - answer->rdLen = get16bits(buffer); - answer->rData = get16bits(buffer); - return answer; -} - -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(int i = start; i < domain.size(); i++) - { - *buffer++ = domain[i]; // last label octets - // llarp::LogInfo("Writing ", domain[i], " at ", i); - } - - *buffer++ = 0; -} - ssize_t raw_sendto_dns_hook_func(void *sock, const struct sockaddr *from, const void *buffer, size_t length) @@ -168,11 +39,13 @@ forward_dns_request(std::string request) return true; } +// FIXME: we need an DNS answer not a sockaddr +// otherwise ttl, type and class can't be relayed correctly void writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from, - dns_request *request) + dnsd_question_request *request) { - lock_t lock(m_dnsd2_Mutex); + //lock_t lock(m_dnsd2_Mutex); if(!hostRes) { llarp::LogWarn("Failed to resolve"); @@ -198,15 +71,15 @@ writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from, put16bits(write_buffer, 0); // AR (number of Additional RRs) // code question - code_domain(write_buffer, request->m_qName); - put16bits(write_buffer, request->m_qType); - put16bits(write_buffer, request->m_qClass); + 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->m_qName); // com, type=6, ttl=0 - put16bits(write_buffer, request->m_qType); - put16bits(write_buffer, request->m_qClass); - put32bits(write_buffer, 1453); // ttl + 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 // has to be a string of 4 bytes struct sockaddr_in *sin = (struct sockaddr_in *)hostRes; @@ -225,12 +98,12 @@ writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from, } void -handle_dnsc_result(dns_client_request *client_request) +handle_dnsc_result(dnsc_answer_request *client_request) { // llarp::LogInfo("phase2 client ", client_request); // writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr - // *from, dns_request *request) - dns_request *server_request = (dns_request *)client_request->user; + // *from, dnsd_question_request *request) + dnsd_question_request *server_request = (dnsd_question_request *)client_request->user; // llarp::Addr test(*server_request->from); // llarp::LogInfo("server request sock ", server_request->from, " is ", test); // llarp::LogInfo("phase2 server ", server_request); @@ -243,9 +116,9 @@ handle_dnsc_result(dns_client_request *client_request) // our generic version void handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from, - dns_request *request) + dnsd_question_request *request) { - lock_t lock(m_dnsd_Mutex); + //lock_t lock(m_dnsd_Mutex); const size_t HDR_OFFSET = 12; const char *p_buffer = buffer; @@ -270,12 +143,16 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from, if(length != 0) m_qName.append(1, '.'); } - request->m_qName = m_qName; - request->m_qType = get16bits(p_buffer); - request->m_qClass = get16bits(p_buffer); - llarp::LogInfo("qName ", m_qName); - llarp::LogInfo("qType ", request->m_qType); - llarp::LogInfo("qClass ", request->m_qClass); + request->question.name = m_qName; + request->question.type = get16bits(p_buffer); + request->question.qClass = get16bits(p_buffer); + + //request->m_qName = m_qName; + //request->m_qType = request->question.type; + //request->m_qClass = request->question.qClass; + llarp::LogInfo("qName ", request->question.name); + llarp::LogInfo("qType ", request->question.type); + llarp::LogInfo("qClass ", request->question.qClass); /* llarp::Addr test(*request->from); @@ -291,20 +168,7 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from, } sockaddr *hostRes = nullptr; - // FIXME: how can we tell the mode? - // struct llarp_udp_io *udp = static_cast(request->user); - if(0) - { - hostRes = resolveHost(m_qName.c_str()); - llarp::Addr anIp(*hostRes); - llarp::LogInfo("DNS got ", anIp); - // writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr - // *from, dns_request *request) - sockaddr *fromCopy = new sockaddr(*from); - writesend_dnss_response(hostRes, fromCopy, request); - } - else + if(request->llarp) { // llarp::Addr anIp; // llarp::LogInfo("Checking server request ", request); @@ -319,23 +183,34 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from, llarp_resolve_host(&dnsd->client, m_qName.c_str(), &handle_dnsc_result, (void *)request); } + else + { + hostRes = raw_resolve_host(m_qName.c_str()); + llarp::Addr anIp(*hostRes); + llarp::LogInfo("DNS got ", anIp); + // writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr + // *from, dnsd_question_request *request) + sockaddr *fromCopy = new sockaddr(*from); + writesend_dnss_response(hostRes, fromCopy, request); + } } // this is called in net threadpool void -llarp_handle_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *paddr, +llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *paddr, const void *buf, ssize_t sz) { - lock_t lock(m_dnsd3_Mutex); + //lock_t lock(m_dnsd3_Mutex); // llarp_link *link = static_cast< llarp_link * >(udp->user); llarp::LogInfo("llarp Received Bytes ", sz); - dns_request *llarp_dns_request = new dns_request; + dnsd_question_request *llarp_dns_request = new dnsd_question_request; // llarp::LogInfo("Creating server request ", &llarp_dns_request); // llarp::LogInfo("Server UDP address ", udp); // make a copy of the sockaddr - llarp_dns_request->from = new sockaddr(*paddr); - llarp_dns_request->user = (void *)udp; + llarp_dns_request->from = new sockaddr(*paddr); + llarp_dns_request->user = (void *)udp; + llarp_dns_request->llarp = true; // set sock hook llarp_dns_request->hook = &llarp_sendto_dns_hook_func; @@ -348,9 +223,10 @@ raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void *buf, ssize_t sz) { llarp::LogInfo("raw Received Bytes ", sz); - dns_request *llarp_dns_request = new dns_request; + dnsd_question_request *llarp_dns_request = new dnsd_question_request; llarp_dns_request->from = (struct sockaddr *)saddr; llarp_dns_request->user = (void *)sockfd; + llarp_dns_request->llarp = false; llarp_dns_request->hook = &raw_sendto_dns_hook_func; handle_recvfrom((char *)buf, sz, saddr, llarp_dns_request); } diff --git a/llarp/dnsd.hpp b/llarp/dnsd.hpp index 47599c99d..9d06939f2 100644 --- a/llarp/dnsd.hpp +++ b/llarp/dnsd.hpp @@ -1,29 +1,56 @@ #ifndef LIBLLARP_DNSD_HPP #define LIBLLARP_DNSD_HPP +#include "dns.hpp" // question and dnsc #include "dnsc.hpp" +#include // for sockaadr 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 }; -dns_msg_header * -decode_hdr(const char *buffer); -dns_msg_question * -decode_question(const char *buffer); -dns_msg_answer * -decode_answer(const char *buffer); +typedef bool (*intercept_query_hook)(struct dnsc_context *); + +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