Loading DnsProxyListener.cpp +14 −5 Original line number Diff line number Diff line Loading @@ -659,11 +659,20 @@ std::string makeThreadName(unsigned netId, uint32_t uid) { } // namespace DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { registerCmd(new GetAddrInfoCmd()); registerCmd(new GetHostByAddrCmd()); registerCmd(new GetHostByNameCmd()); registerCmd(new ResNSendCommand()); registerCmd(new GetDnsNetIdCommand()); mGetAddrInfoCmd = std::make_unique<GetAddrInfoCmd>(); registerCmd(mGetAddrInfoCmd.get()); mGetHostByAddrCmd = std::make_unique<GetHostByAddrCmd>(); registerCmd(mGetHostByAddrCmd.get()); mGetHostByNameCmd = std::make_unique<GetHostByNameCmd>(); registerCmd(mGetHostByNameCmd.get()); mResNSendCommand = std::make_unique<ResNSendCommand>(); registerCmd(mResNSendCommand.get()); mGetDnsNetIdCommand = std::make_unique<GetDnsNetIdCommand>(); registerCmd(mGetDnsNetIdCommand.get()); } void DnsProxyListener::Handler::spawn() { Loading DnsProxyListener.h +6 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,12 @@ class DnsProxyListener : public FrameworkListener { virtual ~GetDnsNetIdCommand() {} int runCommand(SocketClient* c, int argc, char** argv) override; }; std::unique_ptr<GetAddrInfoCmd> mGetAddrInfoCmd; std::unique_ptr<GetHostByAddrCmd> mGetHostByAddrCmd; std::unique_ptr<GetHostByNameCmd> mGetHostByNameCmd; std::unique_ptr<ResNSendCommand> mResNSendCommand; std::unique_ptr<GetDnsNetIdCommand> mGetDnsNetIdCommand; }; } // namespace net Loading Experiments.h +0 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,6 @@ class Experiments { "max_cache_entries", "max_queries_global", "mdns_resolution", "parallel_lookup_release", "parallel_lookup_sleep_time", "retransmission_time_interval", "retry_count", Loading getaddrinfo.cpp +5 −88 Original line number Diff line number Diff line Loading @@ -151,7 +151,6 @@ static bool files_getaddrinfo(const size_t netid, const char* name, const addrin static int _find_src_addr(const struct sockaddr*, struct sockaddr*, unsigned, uid_t, bool allow_v6_linklocal); static int res_queryN(const char* name, res_target* target, ResState* res, int* herrno); static int res_searchN(const char* name, res_target* target, ResState* res, int* herrno); static int res_querydomainN(const char* name, const char* domain, res_target* target, ResState* res, int* herrno); Loading Loading @@ -1603,6 +1602,8 @@ struct QueryResult { NetworkDnsEventReported event; }; // Formulate a normal query, send, and await answer. // Caller must parse answer and determine whether it answers the question. QueryResult doQuery(const char* name, res_target* t, ResState* res, std::chrono::milliseconds sleepTimeMs) { HEADER* hp = (HEADER*)(void*)t->answer.data(); Loading Loading @@ -1640,7 +1641,6 @@ QueryResult doQuery(const char* name, res_target* t, ResState* res, int rcode = NOERROR; n = res_nsend(&res_temp, {buf, n}, {t->answer.data(), anslen}, &rcode, 0, sleepTimeMs); if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { // To ensure that the rcode handling is identical to res_queryN(). if (rcode != RCODE_TIMEOUT) rcode = hp->rcode; // if the query choked with EDNS0, retry without EDNS0 if ((res_temp.netcontext_flags & Loading @@ -1666,6 +1666,8 @@ QueryResult doQuery(const char* name, res_target* t, ResState* res, } // namespace // This function runs doQuery() for each res_target in parallel. // The `target`, which is set in dns_getaddrinfo(), contains at most two res_target. static int res_queryN_parallel(const char* name, res_target* target, ResState* res, int* herrno) { std::vector<std::future<QueryResult>> results; results.reserve(2); Loading Loading @@ -1705,91 +1707,6 @@ static int res_queryN_parallel(const char* name, res_target* target, ResState* r return ancount; } static int res_queryN_wrapper(const char* name, res_target* target, ResState* res, int* herrno) { const bool parallel_lookup = Experiments::getInstance()->getFlag("parallel_lookup_release", 1); if (parallel_lookup) return res_queryN_parallel(name, target, res, herrno); return res_queryN(name, target, res, herrno); } /* * Formulate a normal query, send, and await answer. * Returned answer is placed in supplied buffer "answer". * Perform preliminary check of answer, returning success only * if no error is indicated and the answer count is nonzero. * Return the size of the response on success, -1 on error. * Error number is left in *herrno. * * Caller must parse answer and determine whether it answers the question. */ static int res_queryN(const char* name, res_target* target, ResState* res, int* herrno) { uint8_t buf[MAXPACKET]; int n; struct res_target* t; int rcode; int ancount; assert(name != NULL); /* XXX: target may be NULL??? */ rcode = NOERROR; ancount = 0; for (t = target; t; t = t->next) { HEADER* hp = (HEADER*)(void*)t->answer.data(); bool retried = false; again: hp->rcode = NOERROR; /* default */ /* make it easier... */ int cl = t->qclass; int type = t->qtype; const int anslen = t->answer.size(); LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")"; n = res_nmkquery(QUERY, name, cl, type, {}, buf, res->netcontext_flags); if (n > 0 && (res->netcontext_flags & (NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS)) && !retried) // TODO: remove the retry flag and provide a sufficient test coverage. n = res_nopt(res, n, buf, anslen); if (n <= 0) { LOG(ERROR) << __func__ << ": res_nmkquery failed"; *herrno = NO_RECOVERY; return n; } n = res_nsend(res, {buf, n}, {t->answer.data(), anslen}, &rcode, 0); if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { // Record rcode from DNS response header only if no timeout. // Keep rcode timeout for reporting later if any. if (rcode != RCODE_TIMEOUT) rcode = hp->rcode; // record most recent error // if the query choked with EDNS0, retry without EDNS0 that when the server // has no response, resovler won't retry and do nothing. Even fallback to UDP, // we also has the same symptom if EDNS is enabled. if ((res->netcontext_flags & (NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS)) && (res->flags & RES_F_EDNS0ERR) && !retried) { LOG(DEBUG) << __func__ << ": retry without EDNS0"; retried = true; goto again; } LOG(INFO) << __func__ << ": rcode=" << rcode << ", ancount=" << ntohs(hp->ancount); continue; } ancount += ntohs(hp->ancount); t->n = n; } if (ancount == 0) { *herrno = getHerrnoFromRcode(rcode); return -1; } return ancount; } /* * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. Loading Loading @@ -1936,5 +1853,5 @@ static int res_querydomainN(const char* name, const char* domain, res_target* ta } snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); } return res_queryN_wrapper(longname, target, res, herrno); return res_queryN_parallel(longname, target, res, herrno); } res_query.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -141,8 +141,8 @@ again: LOG(INFO) << __func__ << ": send error"; // Note that rcodes SERVFAIL, NOTIMP, REFUSED may cause res_nquery() to return a general // error code EAI_AGAIN, but mapping the error code from rcode as res_queryN() does for // getaddrinfo(). Different rcodes trigger different behaviors: // error code EAI_AGAIN, but mapping the error code from rcode as res_queryN_parallel() // does for getaddrinfo(). Different rcodes trigger different behaviors: // // - SERVFAIL, NOTIMP, REFUSED // These result in send_dg() returning 0, causing res_nsend() to try the next Loading Loading
DnsProxyListener.cpp +14 −5 Original line number Diff line number Diff line Loading @@ -659,11 +659,20 @@ std::string makeThreadName(unsigned netId, uint32_t uid) { } // namespace DnsProxyListener::DnsProxyListener() : FrameworkListener(SOCKET_NAME) { registerCmd(new GetAddrInfoCmd()); registerCmd(new GetHostByAddrCmd()); registerCmd(new GetHostByNameCmd()); registerCmd(new ResNSendCommand()); registerCmd(new GetDnsNetIdCommand()); mGetAddrInfoCmd = std::make_unique<GetAddrInfoCmd>(); registerCmd(mGetAddrInfoCmd.get()); mGetHostByAddrCmd = std::make_unique<GetHostByAddrCmd>(); registerCmd(mGetHostByAddrCmd.get()); mGetHostByNameCmd = std::make_unique<GetHostByNameCmd>(); registerCmd(mGetHostByNameCmd.get()); mResNSendCommand = std::make_unique<ResNSendCommand>(); registerCmd(mResNSendCommand.get()); mGetDnsNetIdCommand = std::make_unique<GetDnsNetIdCommand>(); registerCmd(mGetDnsNetIdCommand.get()); } void DnsProxyListener::Handler::spawn() { Loading
DnsProxyListener.h +6 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,12 @@ class DnsProxyListener : public FrameworkListener { virtual ~GetDnsNetIdCommand() {} int runCommand(SocketClient* c, int argc, char** argv) override; }; std::unique_ptr<GetAddrInfoCmd> mGetAddrInfoCmd; std::unique_ptr<GetHostByAddrCmd> mGetHostByAddrCmd; std::unique_ptr<GetHostByNameCmd> mGetHostByNameCmd; std::unique_ptr<ResNSendCommand> mResNSendCommand; std::unique_ptr<GetDnsNetIdCommand> mGetDnsNetIdCommand; }; } // namespace net Loading
Experiments.h +0 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,6 @@ class Experiments { "max_cache_entries", "max_queries_global", "mdns_resolution", "parallel_lookup_release", "parallel_lookup_sleep_time", "retransmission_time_interval", "retry_count", Loading
getaddrinfo.cpp +5 −88 Original line number Diff line number Diff line Loading @@ -151,7 +151,6 @@ static bool files_getaddrinfo(const size_t netid, const char* name, const addrin static int _find_src_addr(const struct sockaddr*, struct sockaddr*, unsigned, uid_t, bool allow_v6_linklocal); static int res_queryN(const char* name, res_target* target, ResState* res, int* herrno); static int res_searchN(const char* name, res_target* target, ResState* res, int* herrno); static int res_querydomainN(const char* name, const char* domain, res_target* target, ResState* res, int* herrno); Loading Loading @@ -1603,6 +1602,8 @@ struct QueryResult { NetworkDnsEventReported event; }; // Formulate a normal query, send, and await answer. // Caller must parse answer and determine whether it answers the question. QueryResult doQuery(const char* name, res_target* t, ResState* res, std::chrono::milliseconds sleepTimeMs) { HEADER* hp = (HEADER*)(void*)t->answer.data(); Loading Loading @@ -1640,7 +1641,6 @@ QueryResult doQuery(const char* name, res_target* t, ResState* res, int rcode = NOERROR; n = res_nsend(&res_temp, {buf, n}, {t->answer.data(), anslen}, &rcode, 0, sleepTimeMs); if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { // To ensure that the rcode handling is identical to res_queryN(). if (rcode != RCODE_TIMEOUT) rcode = hp->rcode; // if the query choked with EDNS0, retry without EDNS0 if ((res_temp.netcontext_flags & Loading @@ -1666,6 +1666,8 @@ QueryResult doQuery(const char* name, res_target* t, ResState* res, } // namespace // This function runs doQuery() for each res_target in parallel. // The `target`, which is set in dns_getaddrinfo(), contains at most two res_target. static int res_queryN_parallel(const char* name, res_target* target, ResState* res, int* herrno) { std::vector<std::future<QueryResult>> results; results.reserve(2); Loading Loading @@ -1705,91 +1707,6 @@ static int res_queryN_parallel(const char* name, res_target* target, ResState* r return ancount; } static int res_queryN_wrapper(const char* name, res_target* target, ResState* res, int* herrno) { const bool parallel_lookup = Experiments::getInstance()->getFlag("parallel_lookup_release", 1); if (parallel_lookup) return res_queryN_parallel(name, target, res, herrno); return res_queryN(name, target, res, herrno); } /* * Formulate a normal query, send, and await answer. * Returned answer is placed in supplied buffer "answer". * Perform preliminary check of answer, returning success only * if no error is indicated and the answer count is nonzero. * Return the size of the response on success, -1 on error. * Error number is left in *herrno. * * Caller must parse answer and determine whether it answers the question. */ static int res_queryN(const char* name, res_target* target, ResState* res, int* herrno) { uint8_t buf[MAXPACKET]; int n; struct res_target* t; int rcode; int ancount; assert(name != NULL); /* XXX: target may be NULL??? */ rcode = NOERROR; ancount = 0; for (t = target; t; t = t->next) { HEADER* hp = (HEADER*)(void*)t->answer.data(); bool retried = false; again: hp->rcode = NOERROR; /* default */ /* make it easier... */ int cl = t->qclass; int type = t->qtype; const int anslen = t->answer.size(); LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")"; n = res_nmkquery(QUERY, name, cl, type, {}, buf, res->netcontext_flags); if (n > 0 && (res->netcontext_flags & (NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS)) && !retried) // TODO: remove the retry flag and provide a sufficient test coverage. n = res_nopt(res, n, buf, anslen); if (n <= 0) { LOG(ERROR) << __func__ << ": res_nmkquery failed"; *herrno = NO_RECOVERY; return n; } n = res_nsend(res, {buf, n}, {t->answer.data(), anslen}, &rcode, 0); if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { // Record rcode from DNS response header only if no timeout. // Keep rcode timeout for reporting later if any. if (rcode != RCODE_TIMEOUT) rcode = hp->rcode; // record most recent error // if the query choked with EDNS0, retry without EDNS0 that when the server // has no response, resovler won't retry and do nothing. Even fallback to UDP, // we also has the same symptom if EDNS is enabled. if ((res->netcontext_flags & (NET_CONTEXT_FLAG_USE_DNS_OVER_TLS | NET_CONTEXT_FLAG_USE_EDNS)) && (res->flags & RES_F_EDNS0ERR) && !retried) { LOG(DEBUG) << __func__ << ": retry without EDNS0"; retried = true; goto again; } LOG(INFO) << __func__ << ": rcode=" << rcode << ", ancount=" << ntohs(hp->ancount); continue; } ancount += ntohs(hp->ancount); t->n = n; } if (ancount == 0) { *herrno = getHerrnoFromRcode(rcode); return -1; } return ancount; } /* * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. Loading Loading @@ -1936,5 +1853,5 @@ static int res_querydomainN(const char* name, const char* domain, res_target* ta } snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); } return res_queryN_wrapper(longname, target, res, herrno); return res_queryN_parallel(longname, target, res, herrno); }
res_query.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -141,8 +141,8 @@ again: LOG(INFO) << __func__ << ": send error"; // Note that rcodes SERVFAIL, NOTIMP, REFUSED may cause res_nquery() to return a general // error code EAI_AGAIN, but mapping the error code from rcode as res_queryN() does for // getaddrinfo(). Different rcodes trigger different behaviors: // error code EAI_AGAIN, but mapping the error code from rcode as res_queryN_parallel() // does for getaddrinfo(). Different rcodes trigger different behaviors: // // - SERVFAIL, NOTIMP, REFUSED // These result in send_dg() returning 0, causing res_nsend() to try the next Loading