diff --git a/CMakeLists.txt b/CMakeLists.txt index 1778878df..dd2747fe9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -421,6 +421,7 @@ set(LIB_SRC llarp/context.cpp llarp/crypto_libsodium.cpp llarp/dht.cpp + llarp/dns_rectypes.cpp llarp/dns.cpp llarp/dnsc.cpp llarp/dnsd.cpp @@ -495,6 +496,7 @@ set(DNS_SRC llarp/dnsd.cpp llarp/dns_iptracker.cpp llarp/dns_dotlokilookup.cpp + llarp/dns_rectypes.cpp llarp/net.cpp daemon/dns.cpp ) diff --git a/contrib/py/vanity/readme.md b/contrib/py/vanity/readme.md index dc10e820f..f8161176d 100644 --- a/contrib/py/vanity/readme.md +++ b/contrib/py/vanity/readme.md @@ -5,6 +5,6 @@ installing deps: sudo apt install libsodium-dev pip3 install --user -r requirements.txt -to generate a nonce with a prefix `^loki` using 8 cpu threads: +to generate a nonce with a prefix `^7oki` using 8 cpu threads: - python3 lokinet-vanity.py keyfile.private loki 8 \ No newline at end of file + python3 lokinet-vanity.py keyfile.private 7oki 8 diff --git a/daemon/dns.cpp b/daemon/dns.cpp index d1b8780a9..1ed3f0b74 100644 --- a/daemon/dns.cpp +++ b/daemon/dns.cpp @@ -95,7 +95,10 @@ main(int argc, char *argv[]) // llarp::SetLogLevel(llarp::eLogDebug); - if(1) + bool enableDLL = false; + bool useLlarp = true; + + if(enableDLL) { // libev version w/router context ctx = llarp_main_init(conffname, !TESTNET); @@ -163,7 +166,7 @@ main(int argc, char *argv[]) llarp_main_run(ctx); llarp_main_free(ctx); } - else if(0) + else if(useLlarp) { // libev version llarp_ev_loop *netloop = nullptr; @@ -268,8 +271,31 @@ main(int argc, char *argv[]) continue; llarp::LogInfo("Received Bytes ", nbytes); - raw_handle_recvfrom(&m_sockfd, (const struct sockaddr *)&clientAddress, - buffer, nbytes); + llarp_buffer_t lbuffer; + lbuffer.base = (byte_t *)buffer; + lbuffer.cur = lbuffer.base; + lbuffer.sz = nbytes; + + dns_msg_header *hdr = decode_hdr(lbuffer); + + // if we sent this out, then there's an id + struct dns_tracker *tracker = (struct dns_tracker *)dnsd.client.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); + } + + // raw_handle_recvfrom(&m_sockfd, (const struct sockaddr *)&clientAddress, + // buffer, nbytes); } } diff --git a/include/llarp/aligned.hpp b/include/llarp/aligned.hpp index dc63e5635..f5ee817d7 100644 --- a/include/llarp/aligned.hpp +++ b/include/llarp/aligned.hpp @@ -19,7 +19,7 @@ extern "C" } namespace llarp { - /// aligned buffer, aligns to the nears Long_t + /// aligned buffer that is sz bytes long and aligns to the nears Long_t template < size_t sz, bool randomize = false, typename Long_t = uint64_t > struct AlignedBuffer { diff --git a/include/llarp/dns.h b/include/llarp/dns.h index e196a49b6..728009a37 100644 --- a/include/llarp/dns.h +++ b/include/llarp/dns.h @@ -1,15 +1,6 @@ #ifndef LLARP_DNS_H_ #define LLARP_DNS_H_ -//#include // for sockaadr -//#include // for uint & ssize_t - -// all uint should have been removed in favor of uint_16t -/* non-cygnus does not have this type */ -//#ifdef _WIN32 -//#define uint UINT -//#endif - #ifdef __cplusplus extern "C" { diff --git a/include/llarp/dns.hpp b/include/llarp/dns.hpp index b8c64e769..bcc1c1187 100644 --- a/include/llarp/dns.hpp +++ b/include/llarp/dns.hpp @@ -12,6 +12,15 @@ #endif #include // for llarp::Addr , llarp::huint32_t +#include + +#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 dnsd_context; @@ -73,6 +82,7 @@ struct dns_msg_answer uint32_t ttl; uint16_t rdLen; std::vector< byte_t > rData; + std::unique_ptr< llarp::dns::record > record; }; struct dns_packet @@ -84,12 +94,24 @@ struct dns_packet 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) throw(); +void +vcode_domain(std::vector< byte_t > &bytes, const std::string &domain) throw(); + +void +vput16bits(std::vector< byte_t > &bytes, uint16_t value) throw(); + +void +vput32bits(std::vector< byte_t > &bytes, uint32_t value) throw(); + extern "C" { uint16_t @@ -99,7 +121,7 @@ extern "C" get32bits(const char *&buffer) throw(); dns_msg_header * - decode_hdr(const char *buffer); + decode_hdr(llarp_buffer_t &buffer); dns_msg_question * decode_question(const char *buffer, uint32_t *pos); diff --git a/include/llarp/dns_dotlokilookup.hpp b/include/llarp/dns_dotlokilookup.hpp index f5062a419..988df96f9 100644 --- a/include/llarp/dns_dotlokilookup.hpp +++ b/include/llarp/dns_dotlokilookup.hpp @@ -2,10 +2,6 @@ #define LIBLLARP_DNS_DOTLOKILOOKUP_HPP #include -//#include -//#include -//#include -//#include #include "dnsd.hpp" @@ -38,7 +34,7 @@ struct dotLokiLookup }; dnsd_query_hook_response * -llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from, +llarp_dotlokilookup_handler(std::string name, struct dnsd_question_request *const request); #endif diff --git a/include/llarp/dns_rectypes.hpp b/include/llarp/dns_rectypes.hpp new file mode 100644 index 000000000..efdeb3308 --- /dev/null +++ b/include/llarp/dns_rectypes.hpp @@ -0,0 +1,134 @@ +#ifndef LIBLLARP_DNS_REC_TYPES_HPP +#define LIBLLARP_DNS_REC_TYPES_HPP + +#include +#include // for byte_t +#include // for llarp::Addr , llarp::huint32_t + +namespace llarp +{ + namespace dns + { + struct record + { + virtual ~record() = 0; + record() + { + } + + 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; + + virtual ~type_1a(){}; + 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; + + virtual ~type_2ns(){}; + 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; + + virtual ~type_6soa(){}; + 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; + + virtual ~type_5cname(){}; + 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; + + virtual ~type_12ptr(){}; + 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; + + virtual ~type_15mx(){}; + 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; + + virtual ~type_16txt(){}; + type_16txt(); + + bool + parse(std::vector< byte_t > bytes) override; + + std::vector< byte_t > + to_bytes() override; + }; + + } // namespace dns +} // namespace llarp + +#endif diff --git a/include/llarp/dnsc.hpp b/include/llarp/dnsc.hpp index 69427a3a2..14284c4ba 100644 --- a/include/llarp/dnsc.hpp +++ b/include/llarp/dnsc.hpp @@ -15,8 +15,8 @@ struct dnsc_answer_request; struct dns_query { uint16_t length; - // char *url; unsigned char request[DNC_BUF_SIZE]; + // char *url; // uint16_t reqType; }; @@ -32,17 +32,21 @@ typedef void (*dnsc_answer_hook_func)(dnsc_answer_request *request); struct dnsc_answer_request { /// sock type - void *sock; // pts to udp... + void *sock; // points to udp that sent the request to DNSc... /// customizable (used for hook (outer request)) void *user; - /// storage + /// 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; + + // llarp::huint32_t result; + // std::string revDNS; + // a reference to dnsc_context incase of multiple contexts struct dnsc_context *context; }; @@ -59,9 +63,16 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp, /// 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, + llarp_buffer_t buffer, dns_msg_header *hdr); /// DNS client context (one needed per upstream DNS server) struct dnsc_context @@ -78,13 +89,14 @@ struct dnsc_context struct llarp_logic *logic; }; -/// async resolve a hostname using generic socks +/// 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 resolve a hostname using llarp platform framework +/// 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, diff --git a/include/llarp/dnsd.hpp b/include/llarp/dnsd.hpp index 5bac27ae1..df0d70c7c 100644 --- a/include/llarp/dnsd.hpp +++ b/include/llarp/dnsd.hpp @@ -62,27 +62,26 @@ llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp, // 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 struct sockaddr *from, - dnsd_question_request *request); +write404_dnss_response(dnsd_question_request *request); /// for hook functions to use void -writecname_dnss_response(std::string cname, const struct sockaddr *from, - dnsd_question_request *request); +writecname_dnss_response(std::string cname, dnsd_question_request *request); // FIXME: llarp::Addr /// send an A record found response void -writesend_dnss_response(llarp::huint32_t *hostRes, const struct sockaddr *from, +writesend_dnss_response(llarp::huint32_t *hostRes, dnsd_question_request *request); // FIXME: llarp::Addr /// send an PTR record found response void -writesend_dnss_revresponse(std::string reverse, const struct sockaddr *from, - dnsd_question_request *request); +writesend_dnss_revresponse(std::string reverse, dnsd_question_request *request); // FIXME: llarp::Addr // @@ -91,8 +90,7 @@ writesend_dnss_revresponse(std::string reverse, const struct sockaddr *from, /// intercept query hook functor using intercept_query_hook = std::function< dnsd_query_hook_response *( - std::string name, const struct sockaddr *from, - struct dnsd_question_request *request) >; + std::string name, struct dnsd_question_request *request) >; // FIXME: llarp::Addr /// DNS Server context diff --git a/include/llarp/exit/endpoint.hpp b/include/llarp/exit/endpoint.hpp index fd101cfab..251dd5851 100644 --- a/include/llarp/exit/endpoint.hpp +++ b/include/llarp/exit/endpoint.hpp @@ -35,6 +35,10 @@ namespace llarp bool ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 5000) const; + /// return true if this endpoint looks dead right now + bool + LooksDead(llarp_time_t now, llarp_time_t timeout = 10000) const; + /// tick ourself, reset tx/rx rates void Tick(llarp_time_t now); @@ -92,6 +96,7 @@ namespace llarp llarp::PathID_t m_CurrentPath; llarp::huint32_t m_IP; uint64_t m_TxRate, m_RxRate; + llarp_time_t m_LastActive; bool m_RewriteSource; }; } // namespace exit diff --git a/include/llarp/handlers/exit.hpp b/include/llarp/handlers/exit.hpp index 14f78f381..94613956c 100644 --- a/include/llarp/handlers/exit.hpp +++ b/include/llarp/handlers/exit.hpp @@ -44,6 +44,9 @@ namespace llarp llarp_router* Router(); + llarp_time_t + Now() const; + llarp_crypto* Crypto(); diff --git a/include/llarp/service/Info.hpp b/include/llarp/service/Info.hpp index 405c7a2f0..62c091c47 100644 --- a/include/llarp/service/Info.hpp +++ b/include/llarp/service/Info.hpp @@ -13,9 +13,10 @@ namespace llarp private: llarp::PubKey enckey; llarp::PubKey signkey; - VanityNonce vanity; - + public: + VanityNonce vanity; + ServiceInfo() = default; ServiceInfo(ServiceInfo&& other) @@ -57,10 +58,12 @@ namespace llarp } bool - Update(const byte_t* enc, const byte_t* sign) + Update(const byte_t* enc, const byte_t* sign, const byte_t * nonce=nullptr) { enckey = enc; signkey = sign; + if(nonce) + vanity = nonce; return UpdateAddr(); } diff --git a/include/tl/optional.hpp b/include/tl/optional.hpp index 7c6a4d669..520862c70 100644 --- a/include/tl/optional.hpp +++ b/include/tl/optional.hpp @@ -108,7 +108,7 @@ namespace tl /// \exclude #define TL_OPTIONAL_11_CONSTEXPR #else -/// \exclude + /// \exclude #define TL_OPTIONAL_11_CONSTEXPR constexpr #endif diff --git a/libutp/utp_internal.cpp b/libutp/utp_internal.cpp index b56b2ec0e..be834c686 100644 --- a/libutp/utp_internal.cpp +++ b/libutp/utp_internal.cpp @@ -1233,6 +1233,7 @@ UTPSocket::write_outgoing_packet(size_t payload, uint flags, last_rcv_win = get_rcv_window(); PacketFormatV1 *p1 = (PacketFormatV1 *)pkt->data; + // p1->ver_type; needs to be set!! p1->set_version(1); p1->set_type(flags); p1->ext = 0; diff --git a/llarp/dns.cpp b/llarp/dns.cpp index 156c4abc9..24c2cda15 100644 --- a/llarp/dns.cpp +++ b/llarp/dns.cpp @@ -124,10 +124,171 @@ code_domain(char *&buffer, const std::string &domain) throw() *buffer++ = 0; } -// lets just remove uint -#ifdef _WIN32 -#define uint UINT -#endif +void +vcode_domain(std::vector< byte_t > &bytes, const std::string &domain) throw() +{ + 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) throw() +{ + 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) throw() +{ + 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) +{ + llarp::dns::type_1a *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()); + } + + llarp::dns::type_2ns *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()); + } + + llarp::dns::type_5cname *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()); + } + + llarp::dns::type_12ptr *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()); + } + llarp::dns::type_15mx *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()); + } + llarp::dns::type_16txt *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" { @@ -148,13 +309,24 @@ extern "C" } dns_msg_header * - decode_hdr(const char *buffer) + decode_hdr(llarp_buffer_t &buffer) { dns_msg_header *hdr = new dns_msg_header; - hdr->id = get16bits(buffer); - uint16_t fields = get16bits(buffer); - uint8_t lFields = (fields & 0x00FF) >> 0; - uint8_t hFields = (fields & 0xFF00) >> 8; + uint16_t fields; + + // reads as network byte order + llarp_buffer_read_uint16(&buffer, &hdr->id); + llarp_buffer_read_uint16(&buffer, &fields); + llarp_buffer_read_uint16(&buffer, &hdr->qdCount); + llarp_buffer_read_uint16(&buffer, &hdr->anCount); + llarp_buffer_read_uint16(&buffer, &hdr->nsCount); + llarp_buffer_read_uint16(&buffer, &hdr->arCount); + + // 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; @@ -162,68 +334,32 @@ extern "C" 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; - 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, uint32_t *pos) { - // char *start = (char *)buffer; dns_msg_question *question = new dns_msg_question; - // uint32_t start = *pos; std::string m_qName = getDNSstring(buffer, pos); llarp::LogDebug("Got question name: ", m_qName); - // llarp::LogInfo("Started at ", std::to_string(start), " ended at: ", - // std::to_string(*pos)); llarp::LogInfo("Advancing question buffer by ", - // std::to_string(*pos)); buffer += (*pos) - start; buffer += - // m_qName.length() + 2; // + length byte & ending terminator const char *moveable = buffer; moveable += *pos; // advance to position - // hexDump(moveable, 4); - - // printf("Now0 at [%d]\n", buffer - start); - // buffer += m_qName.size() + 1; - /* - 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(moveable); (*pos) += 2; - // printf("Now1 at [%d]\n", buffer - start); question->qClass = get16bits(moveable); (*pos) += 2; - // printf("Now2 at [%d]\n", buffer - start); - /* - llarp::LogDebug("Type ", std::to_string(question->type), " Class ", - std::to_string(question->qClass)); - */ - // hexDump(moveable, 4); return question; } @@ -323,6 +459,9 @@ extern "C" */ moveable += answer->rdLen; (*pos) += answer->rdLen; // advance the length + + answer->record = std::make_unique< llarp::dns::type_1a >(); + answer->record->parse(answer->rData); } else { @@ -330,16 +469,36 @@ extern "C" // FIXME: move this out of here, this shouldn't be responsible for decode switch(answer->type) { - case 2: // NS + 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 - break; - case 5: + //(*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 - break; - case 6: // type 6 = SOA + //(*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 @@ -367,19 +526,22 @@ extern "C" (*pos) += answer->rdLen; // advance the length } break; - case 12: + 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(answer->rdLen); - memcpy(answer->rData.data(), revname.c_str(), answer->rdLen); + 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 15: + case LLARP_DNS_RECTYPE_MX: { uint16_t priority = get16bits(moveable); (*pos) += 2; @@ -393,9 +555,12 @@ extern "C" // 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 16: + case LLARP_DNS_RECTYPE_TXT: { // hexDump(buffer, 5); // std::string revname = getDNSstring((char *)buffer); @@ -404,6 +569,9 @@ extern "C" 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 @@ -436,10 +604,14 @@ extern "C" const struct sockaddr *addr, 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; + // auto abuffer = llarp::StackBuffer< decltype(buf) >(buf); + + llarp_buffer_t buffer; + buffer.base = (byte_t *)buf; + buffer.cur = buffer.base; + buffer.sz = sz; + + dns_msg_header *hdr = decode_hdr(buffer); llarp::LogDebug("msg id ", hdr->id); llarp::LogDebug("msg qr ", (uint8_t)hdr->qr); if(!udp) @@ -461,23 +633,5 @@ extern "C" llarp_handle_dnsd_recvfrom(udp, addr, buf, sz); } delete hdr; - /* - llarp::LogInfo("msg op ", hdr->opcode); - llarp::LogInfo("msg rc ", hdr->rcode); - - for(uint8_t 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(uint8_t 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_dotlokilookup.cpp b/llarp/dns_dotlokilookup.cpp index 2aea964a6..5e8f63547 100644 --- a/llarp/dns_dotlokilookup.cpp +++ b/llarp/dns_dotlokilookup.cpp @@ -23,7 +23,8 @@ random_string(size_t len = 15, std::string const &allowed_chars = default_chars) struct check_query_simple_request { - const struct sockaddr *from; // source + // already inside request + // const struct sockaddr *from; // source dnsd_question_request *request; }; @@ -44,7 +45,7 @@ llarp_dotlokilookup_checkQuery(void *u, __attribute__((unused)) uint64_t orig, if(!dll) { llarp::LogError("DNSd dotLokiLookup is not configured"); - write404_dnss_response(qr->from, qr->request); + write404_dnss_response(qr->request); delete qr; return; } @@ -58,7 +59,7 @@ llarp_dotlokilookup_checkQuery(void *u, __attribute__((unused)) uint64_t orig, { llarp::LogWarn("Could not base32 decode address: ", qr->request->question.name); - write404_dnss_response(qr->from, qr->request); + write404_dnss_response(qr->request); delete qr; return; } @@ -85,7 +86,7 @@ llarp_dotlokilookup_checkQuery(void *u, __attribute__((unused)) uint64_t orig, if(!routerHiddenServiceContext) { llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user); - write404_dnss_response(qr->from, qr->request); + write404_dnss_response(qr->request); delete qr; return; } @@ -95,7 +96,7 @@ llarp_dotlokilookup_checkQuery(void *u, __attribute__((unused)) uint64_t orig, if(!tunIp->h) { llarp::LogWarn("dotLokiLookup failed to map address"); - write404_dnss_response(qr->from, qr->request); + write404_dnss_response(qr->request); delete qr; return; } @@ -142,7 +143,7 @@ llarp_dotlokilookup_checkQuery(void *u, __attribute__((unused)) uint64_t orig, llarp::huint32_t foundAddr; if(!routerHiddenServiceContext->FindBestAddressFor(addr, foundAddr)) { - write404_dnss_response(qr->from, qr->request); + write404_dnss_response(qr->request); delete qr; return; } @@ -160,7 +161,7 @@ llarp_dotlokilookup_checkQuery(void *u, __attribute__((unused)) uint64_t orig, // saddr.sin_addr.s_addr = llarp::xhtonl(foundAddr).n; // FIXME: flush cache to disk // on crash we'll need to bring up all the same IPs we assigned before... - writesend_dnss_response(&foundAddr, qr->from, qr->request); + writesend_dnss_response(&foundAddr, qr->request); delete qr; return; } @@ -188,7 +189,7 @@ split(std::string str) struct reverse_handler_iter_context { std::string lName; - const struct sockaddr *from; + // const struct sockaddr *from; // aready inside dnsd_question_request const struct dnsd_question_request *request; }; @@ -260,13 +261,12 @@ ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg) searchIPv4_fixed); if(addr.IsZero()) { - write404_dnss_response(context->from, - (dnsd_question_request *)context->request); + write404_dnss_response((dnsd_question_request *)context->request); } else { // llarp::LogInfo("Returning [", addr.ToString(), "]"); - writesend_dnss_revresponse(addr.ToString(), context->from, + writesend_dnss_revresponse(addr.ToString(), (dnsd_question_request *)context->request); } return false; @@ -275,7 +275,7 @@ ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg) } dnsd_query_hook_response * -llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from, +llarp_dotlokilookup_handler(std::string name, struct dnsd_question_request *const request) { dnsd_query_hook_response *response = new dnsd_query_hook_response; @@ -303,8 +303,8 @@ llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from, // which range? // for each tun interface struct reverse_handler_iter_context context; - context.lName = lName; - context.from = from; + context.lName = lName; + // context.from = request->from; context.request = request; struct llarp::service::Context::endpoint_iter i; @@ -362,8 +362,8 @@ llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from, // schedule future response check_query_simple_request *qr = new check_query_simple_request; - qr->from = from; - qr->request = request; + // qr->from = request->from; + qr->request = request; auto tun = routerHiddenServiceContext->getFirstTun(); if(tun->HasPathToService(addr)) diff --git a/llarp/dns_rectypes.cpp b/llarp/dns_rectypes.cpp new file mode 100644 index 000000000..402659689 --- /dev/null +++ b/llarp/dns_rectypes.cpp @@ -0,0 +1,207 @@ +#include +#include // for vput16bits() + +namespace llarp +{ + namespace dns + { + record::~record(){ + + }; + + 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(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 diff --git a/llarp/dnsc.cpp b/llarp/dnsc.cpp index fe5501dd8..1c9787f30 100644 --- a/llarp/dnsc.cpp +++ b/llarp/dnsc.cpp @@ -124,6 +124,8 @@ answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url, request->question.type = type; request->question.qClass = 1; + request->packet.header = nullptr; + // register our self with the tracker dns_tracker *tracker = request->context->tracker; if(!tracker) @@ -151,18 +153,8 @@ answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url, /// generic dnsc handler void generic_handle_dnsc_recvfrom(dnsc_answer_request *request, - __attribute__((unused)) - const struct sockaddr *saddr, - const void *buf, ssize_t sz) + llarp_buffer_t buffer, dns_msg_header *hdr) { - // 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); - dns_msg_header *hdr = decode_hdr((const char *)castBuf); - - llarp::LogDebug("Header got client responses for id: ", hdr->id); if(!request) { llarp::LogError( @@ -170,14 +162,15 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request, // we can't call back the hook return; } - // llarp_dnsc_unbind(request); + // llarp::LogInfo("got a response, udp user is ", udp->user); - if(sz < 0) - { - llarp::LogWarn("Error Receiving DNS Client Response"); - request->resolved(request); - return; - } + // 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); @@ -203,44 +196,49 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request, // rcode = (buffer[3] & 0x0F); // llarp::LogInfo("dnsc rcode ", rcode); - dns_msg_header *msg = decode_hdr((const char *)castBuf); - castBuf += 12; - llarp::LogDebug("msg id ", msg->id); - uint8_t qr = msg->qr; + // 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 = msg->opcode; + uint8_t opcode = hdr->opcode; llarp::LogDebug("msg op ", opcode); - rcode = msg->rcode; + rcode = hdr->rcode; llarp::LogDebug("msg rc ", rcode); - llarp::LogDebug("msg qdc ", msg->qdCount); - llarp::LogDebug("msg anc ", msg->anCount); - llarp::LogDebug("msg nsc ", msg->nsCount); - llarp::LogDebug("msg arc ", msg->arCount); + 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(castBufc, &pos); + 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 } - llarp::LogDebug("Question ", std::to_string(question->type), " ", - question->name); - + 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(castBufc, &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)); @@ -295,12 +293,32 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request, for(uint32_t i = 0; i < hdr->nsCount; i++) { // pos = 0; // reset pos - answer = decode_answer(castBufc, &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)); + /* + 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((ssize_t)pos > sz) + if((size_t)pos > sz) { llarp::LogWarn("Would read past end of dns packet. for ", request->question.name); @@ -359,7 +377,10 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request, answer = answers.front(); } - llarp::LogDebug("qus type ", question->type); + if(question) + { + llarp::LogDebug("qus type ", question->type); + } llarp::LogDebug("ans class ", answer->aClass); llarp::LogDebug("ans type ", answer->type); @@ -408,7 +429,21 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request, llarp::LogDebug("request question type: ", std::to_string(request->question.type)); */ - if(request->question.type == 1) + // 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, ":"); @@ -440,9 +475,11 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request, // 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); @@ -461,37 +498,45 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request, 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 = std::string((char *)answer->rData.data(), + // answer->rData.size()); + // request->revDNS = record->revname; request->resolved(request); return; } - else if(request->question.type == 15) + else if(answer->type == 15) { - llarp::LogDebug("Resolving MX"); - request->found = true; - request->result.h = 99; - request->revDNS = - std::string((char *)answer->rData.data(), answer->rData.size()); + llarp::dns::type_15mx *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(request->question.type == 16) + else if(answer->type == 16) { llarp::LogDebug("Resolving TXT"); request->found = true; - request->revDNS = - std::string((char *)answer->rData.data(), answer->rData.size()); + // request->revDNS = std::string((char *)answer->rData.data(), + // answer->rData.size()); request->resolved(request); return; } - else if(request->question.type == 28) + 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 @@ -530,6 +575,7 @@ raw_resolve_host(struct dnsc_context *const dnsc, const char *url, if(!(sockfd > 0)) { llarp::LogWarn("Error creating socket!\n"); + delete dns_packet; return; } // socket = sockfd; @@ -567,7 +613,11 @@ raw_resolve_host(struct dnsc_context *const dnsc, const char *url, return; } llarp::LogInfo("closing new socket\n"); - + if(!size) + { + llarp::LogWarn("Error Receiving DNS Client Response"); + return; + } // hexdump("received packet", &buffer, ret); #ifndef _WIN32 @@ -576,15 +626,30 @@ raw_resolve_host(struct dnsc_context *const dnsc, const char *url, closesocket(sockfd); #endif - unsigned char *castBuf = (unsigned char *)buffer; + 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 = decode_hdr((const char *)castBuf); + dns_msg_header *hdr = decode_hdr(lbuffer); llarp::LogInfo("response header says it belongs to id #", hdr->id); // if we sent this out, then there's an id - struct dns_tracker *tracker = (struct dns_tracker *)dnsc->tracker; - generic_handle_dnsc_recvfrom(tracker->client_request[hdr->id].get(), nullptr, - castBuf, size); + struct dns_tracker *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 @@ -597,9 +662,21 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp, { llarp::LogWarn("saddr isnt set"); } - unsigned char *castBuf = (unsigned char *)buf; + if(sz < 0) + { + llarp::LogWarn("Error Receiving DNS Client Response"); + return; + } + + llarp_buffer_t buffer; + buffer.base = (byte_t *)buf; + buffer.cur = buffer.base; + buffer.sz = sz; + + // unsigned char *castBuf = (unsigned char *)buf; // auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf); - dns_msg_header *hdr = decode_hdr((const char *)castBuf); + dns_msg_header *hdr = decode_hdr(buffer); + buffer.cur = buffer.base; // reset cursor to beginning llarp::LogDebug("Header got client responses for id: ", hdr->id); @@ -610,7 +687,8 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp, // sometimes we'll get double responses if(request) { - generic_handle_dnsc_recvfrom(request, saddr, buf, sz); + request->packet.header = hdr; + generic_handle_dnsc_recvfrom(request, buffer, hdr); } else { diff --git a/llarp/dnsd.cpp b/llarp/dnsd.cpp index b3bdb6b03..0122e1182 100644 --- a/llarp/dnsd.cpp +++ b/llarp/dnsd.cpp @@ -39,8 +39,7 @@ llarp_sendto_dns_hook_func(void *sock, const struct sockaddr *from, } void -write404_dnss_response(const struct sockaddr *from, - dnsd_question_request *request) +write404_dnss_response(dnsd_question_request *request) { char buf[BUFFER_SIZE] = {0}; @@ -75,12 +74,11 @@ write404_dnss_response(const struct sockaddr *from, 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, from, buf, out_bytes); + request->sendto_hook(request->user, request->from, buf, out_bytes); } void -writecname_dnss_response(std::string cname, const struct sockaddr *from, - dnsd_question_request *request) +writecname_dnss_response(std::string cname, dnsd_question_request *request) { char buf[BUFFER_SIZE] = {0}; @@ -113,7 +111,7 @@ writecname_dnss_response(std::string cname, const struct sockaddr *from, put32bits(write_buffer, 1); // ttl put16bits(write_buffer, cname.length() + 2); // rdLength - code_domain(write_buffer, cname); // com, type=6, ttl=0 + code_domain(write_buffer, cname); // // location of cname //*write_buffer++ = ip[0]; //*write_buffer++ = ip[1]; @@ -143,12 +141,11 @@ writecname_dnss_response(std::string cname, const struct sockaddr *from, 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, from, buf, out_bytes); + request->sendto_hook(request->user, request->from, buf, out_bytes); } void -writesend_dnss_revresponse(std::string reverse, const struct sockaddr *from, - dnsd_question_request *request) +writesend_dnss_revresponse(std::string reverse, dnsd_question_request *request) { char buf[BUFFER_SIZE] = {0}; @@ -182,13 +179,13 @@ writesend_dnss_revresponse(std::string reverse, const struct sockaddr *from, 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, from, buf, out_bytes); + request->sendto_hook(request->user, request->from, 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 struct sockaddr *from, +writesend_dnss_response(llarp::huint32_t *hostRes, dnsd_question_request *request) { // llarp::Addr test(*from); @@ -196,7 +193,7 @@ writesend_dnss_response(llarp::huint32_t *hostRes, const struct sockaddr *from, if(!hostRes) { llarp::LogWarn("Failed to resolve ", request->question.name); - write404_dnss_response(from, request); + write404_dnss_response(request); return; } @@ -250,7 +247,7 @@ writesend_dnss_response(llarp::huint32_t *hostRes, const struct sockaddr *from, 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, buf, out_bytes); + request->sendto_hook(request->user, request->from, buf, out_bytes); } void @@ -349,8 +346,22 @@ handle_dnsc_result(dnsc_answer_request *client_request) llarp::LogError("Couldn't map client requser user to a server request"); return; } + + client_request->packet.header->id = server_request->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, + test.data(), test.size()); + + 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, @@ -380,20 +391,20 @@ handle_dnsc_result(dnsc_answer_request *client_request) writesend_dnss_response(useHostRes, server_request->from, server_request); } llarp_host_resolved(client_request); + */ } // our generic version void -handle_recvfrom(const char *buffer, __attribute__((unused)) ssize_t nbytes, - const struct sockaddr *from, dnsd_question_request *request) +handle_recvfrom(llarp_buffer_t buffer, dnsd_question_request *request) { const size_t HDR_OFFSET = 12; - const char *p_buffer = buffer; + const char *p_buffer = (const char *)buffer.base; int rcode = (buffer[3] & 0x0F); llarp::LogDebug("dnsd rcode ", rcode); - dns_msg_header *msg = decode_hdr(p_buffer); + dns_msg_header *msg = decode_hdr(buffer); p_buffer += HDR_OFFSET; request->id = msg->id; std::string m_qName = ""; @@ -424,8 +435,8 @@ handle_recvfrom(const char *buffer, __attribute__((unused)) ssize_t nbytes, llarp::LogInfo("DNS request from ", test2); */ - sockaddr *fromCopy = - new sockaddr(*from); // make our own sockaddr that won't get cleaned up + // sockaddr *fromCopy = new sockaddr(*from); // make our own sockaddr that + // won't get cleaned up if(!request) { llarp::LogError("request is not configured"); @@ -441,7 +452,7 @@ handle_recvfrom(const char *buffer, __attribute__((unused)) ssize_t nbytes, // llarp::Addr test(*from); // llarp::LogInfo("from ", test); dnsd_query_hook_response *intercept = - request->context->intercept(request->question.name, fromCopy, request); + request->context->intercept(request->question.name, request); // if(!forward_dns_request(m_qName)) if(intercept != nullptr) { @@ -455,7 +466,7 @@ handle_recvfrom(const char *buffer, __attribute__((unused)) ssize_t nbytes, { llarp::LogDebug("HOOKED: sending an immediate override"); // told that hook will handle overrides - writesend_dnss_response(intercept->returnThis, fromCopy, request); + writesend_dnss_response(intercept->returnThis, request); return; } } @@ -465,7 +476,7 @@ handle_recvfrom(const char *buffer, __attribute__((unused)) ssize_t nbytes, if(!request->context) { llarp::LogError("dnsd request context was not a dnsd context"); - writesend_dnss_response(nullptr, fromCopy, request); + writesend_dnss_response(nullptr, request); return; } /* @@ -486,7 +497,8 @@ handle_recvfrom(const char *buffer, __attribute__((unused)) ssize_t nbytes, return; } */ - delete fromCopy; + // delete fromCopy; + // call DNSc if(request->llarp) { // make async request @@ -524,12 +536,17 @@ llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp, &llarp_sendto_dns_hook_func; // set sock hook // llarp::LogInfo("Server request's UDP ", llarp_dns_request->user); - handle_recvfrom((char *)buf, sz, llarp_dns_request->from, llarp_dns_request); + llarp_buffer_t buffer; + buffer.base = (byte_t *)buf; + buffer.cur = buffer.base; + buffer.sz = sz; + + handle_recvfrom(buffer, llarp_dns_request); } void -raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void *buf, - ssize_t sz) +raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, + llarp_buffer_t buffer) { if(!dns_udp_tracker.dnsd) { @@ -543,7 +560,8 @@ raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void *buf, llarp_dns_request->user = (void *)sockfd; llarp_dns_request->llarp = false; llarp_dns_request->sendto_hook = &raw_sendto_dns_hook_func; - handle_recvfrom((char *)buf, sz, llarp_dns_request->from, llarp_dns_request); + + handle_recvfrom(buffer, llarp_dns_request); } bool diff --git a/llarp/exit/endpoint.cpp b/llarp/exit/endpoint.cpp index c50b81bf7..c990964cd 100644 --- a/llarp/exit/endpoint.cpp +++ b/llarp/exit/endpoint.cpp @@ -14,6 +14,7 @@ namespace llarp , m_IP(ip) , m_RewriteSource(rewriteIP) { + m_LastActive = parent->Now(); } Endpoint::~Endpoint() @@ -65,6 +66,15 @@ namespace llarp return true; } + bool Endpoint::LooksDead(llarp_time_t now, llarp_time_t timeout) const + { + if(ExpiresSoon(now, timeout)) + return true; + if (now > m_LastActive) + return now - m_LastActive > timeout; + return true; + } + bool Endpoint::SendOutboundTraffic(llarp_buffer_t buf) { @@ -83,6 +93,7 @@ namespace llarp return false; } m_TxRate += buf.sz; + m_LastActive = m_Parent->Now(); return true; } diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 669532b32..0e1958712 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -37,10 +37,16 @@ namespace llarp { } + llarp_time_t + ExitEndpoint::Now() const + { + return m_Router->Now(); + } + void ExitEndpoint::FlushInbound() { - auto now = Router()->Now(); + auto now = Now(); m_InetToNetwork.Process([&](Pkt_t &pkt) { llarp::PubKey pk; { @@ -58,23 +64,27 @@ namespace llarp auto range = m_ActiveExits.equal_range(pk); auto itr = range.first; uint64_t min = std::numeric_limits< uint64_t >::max(); - /// pick path with lowest tx rate + /// pick non dead looking path with lowest tx rate while(itr != range.second) { - if(ep == nullptr) - ep = itr->second.get(); - else if(itr->second->RxRate() < min && !itr->second->ExpiresSoon(now)) + if(itr->second->TxRate() < min && !itr->second->LooksDead(now)) { - min = ep->TxRate(); ep = itr->second.get(); + min = ep->TxRate(); } ++itr; } - if(ep) + + if(ep == nullptr) + { + // we may have all dead sessions, wtf now? + llarp::LogWarn(Name(), " dropped inbound traffic for session ", pk, " as we have no working endpoints"); + } + else { if(!ep->SendInboundTraffic(pkt.Buffer())) { - llarp::LogWarn(Name(), " dropped inbound traffic for session ", pk); + llarp::LogWarn(Name(), " dropped inbound traffic for session ", pk, " as we are overloaded (probably)"); } } }); @@ -299,10 +309,10 @@ namespace llarp if(wantInternet && !m_PermitExit) return false; huint32_t ip = GetIPForIdent(pk); - m_ActiveExits.insert(std::make_pair( - pk, - std::unique_ptr< llarp::exit::Endpoint >( - new llarp::exit::Endpoint(pk, path, !wantInternet, ip, this)))); + m_ActiveExits.insert( + std::make_pair(pk, + std::make_unique< llarp::exit::Endpoint >( + pk, path, !wantInternet, ip, this))); m_Paths[path] = pk; return HasLocalMappedAddrFor(pk); } @@ -354,4 +364,4 @@ namespace llarp } } } // namespace handlers -} // namespace llarp \ No newline at end of file +} // namespace llarp diff --git a/llarp/net_addr.cpp b/llarp/net_addr.cpp index 0188310f5..fc1387992 100644 --- a/llarp/net_addr.cpp +++ b/llarp/net_addr.cpp @@ -114,8 +114,26 @@ namespace llarp } bool - Addr::from_char_array(const char* str) + Addr::from_char_array(const char* in) { + char* str = (char*)in; + char* pPosition = strchr(str, ':'); + bool freeStr = false; + if(pPosition) + { + // parse port + char buf[6]; + snprintf(buf, 6, "%s", pPosition + 1); + uint16_t port = std::atoi(buf); + llarp::LogDebug("Setting port ", std::to_string(port)); + this->port(port); + // trim str + // can't VLA + str = strdup(in); // copy it + str[pPosition - in] = '\0'; // nul terminate it early + llarp::LogDebug("Truncating to ", str); + freeStr = true; + } llarp::Zero(&_addr, sizeof(sockaddr_in6)); struct addrinfo hint, *res = NULL; int ret; @@ -129,17 +147,23 @@ namespace llarp if(ret) { llarp::LogError("failed to determine address family: ", str); + if(freeStr) + free(str); return false; } if(res->ai_family == AF_INET6) { llarp::LogError("IPv6 address not supported yet", str); + if(freeStr) + free(str); return false; } else if(res->ai_family != AF_INET) { llarp::LogError("Address family not supported yet", str); + if(freeStr) + free(str); return false; } @@ -148,8 +172,12 @@ namespace llarp if(inet_aton(str, addr) == 0) { llarp::LogError("failed to parse ", str); + if(freeStr) + free(str); return false; } + if(freeStr) + free(str); _addr.sin6_family = res->ai_family; _addr4.sin_family = res->ai_family; diff --git a/llarp/service.cpp b/llarp/service.cpp index 2860d0ca6..e2d563587 100644 --- a/llarp/service.cpp +++ b/llarp/service.cpp @@ -262,9 +262,13 @@ namespace llarp inf.read((char*)buf.base, sz); if(!BDecode(&buf)) return false; - // update pubkey + + const byte_t * ptr = nullptr; + if(!vanity.IsZero()) + ptr = vanity.data(); + // update pubkeys pub.Update(llarp::seckey_topublic(enckey), - llarp::seckey_topublic(signkey)); + llarp::seckey_topublic(signkey), ptr); return true; } diff --git a/test/test_dns_unit.cpp b/test/test_dns_unit.cpp index 4536007ad..72dc90602 100644 --- a/test/test_dns_unit.cpp +++ b/test/test_dns_unit.cpp @@ -28,9 +28,13 @@ struct DNSTest : public ::testing::Test // 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 @@ -87,7 +91,8 @@ TEST_F(DNSTest, TestCodeDomain) // test decoders TEST_F(DNSTest, TestDecodeHdr) { - dns_msg_header *hdr = decode_hdr((char *)this->buf); + + dns_msg_header *hdr = decode_hdr(this->buffer_t); /* printf("id[%d]", hdr->id); printf("qr[%d]", hdr->qr); diff --git a/test/test_dnsd_unit.cpp b/test/test_dnsd_unit.cpp index a038ccf79..42ad18a75 100644 --- a/test/test_dnsd_unit.cpp +++ b/test/test_dnsd_unit.cpp @@ -50,7 +50,7 @@ struct llarpDNSdTest : public ::testing::Test TEST_F(llarpDNSdTest, TestNxDomain) { - write404_dnss_response(nullptr, &test_request); + 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 " @@ -65,7 +65,7 @@ TEST_F(llarpDNSdTest, TestAResponse) llarp::Zero(&hostRes.h, sizeof(uint32_t)); // sockaddr hostRes; // llarp::Zero(&hostRes, sizeof(sockaddr)); - writesend_dnss_response(&hostRes, nullptr, &test_request); + 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 " @@ -76,7 +76,7 @@ TEST_F(llarpDNSdTest, TestAResponse) TEST_F(llarpDNSdTest, TestPTRResponse) { - writesend_dnss_revresponse("loki.network", nullptr, &test_request); + 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 " @@ -87,7 +87,7 @@ TEST_F(llarpDNSdTest, TestPTRResponse) TEST_F(llarpDNSdTest, TestCname) { - writecname_dnss_response("test.cname", nullptr, &test_request); + 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 "