Loading Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ cc_library { "res_query.cpp", "res_send.cpp", "res_stats.cpp", "util.cpp", "Dns64Configuration.cpp", "DnsProxyListener.cpp", "DnsResolver.cpp", Loading DnsProxyListener.cpp +6 −9 Original line number Diff line number Diff line Loading @@ -74,10 +74,6 @@ namespace { // Limits the number of outstanding DNS queries by client UID. constexpr int MAX_QUERIES_PER_UID = 256; // Max packet size for answer, sync with getaddrinfo.c // TODO: switch to dynamically allocated buffers with std::vector constexpr int MAXPACKET = 8 * 1024; android::netdutils::OperationLimiter<uid_t> queryLimiter(MAX_QUERIES_PER_UID); void logArguments(int argc, char** argv) { Loading Loading @@ -886,12 +882,13 @@ void DnsProxyListener::ResNSendHandler::run() { // Send DNS query std::vector<uint8_t> ansBuf(MAXPACKET, 0); int arcode, nsendAns = -1; int rcode = ns_r_noerror; int nsendAns = -1; NetworkDnsEventReported event; initDnsEvent(&event); if (queryLimiter.start(uid)) { nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET, &arcode, static_cast<ResNsendFlags>(mFlags), &event); &rcode, static_cast<ResNsendFlags>(mFlags), &event); queryLimiter.finish(uid); } else { LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid Loading @@ -909,13 +906,13 @@ void DnsProxyListener::ResNSendHandler::run() { sendBE32(mClient, nsendAns); if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, arcode), event, rr_name); resNSendToAiError(nsendAns, rcode), event, rr_name); } return; } // Send rcode if (!sendBE32(mClient, arcode)) { if (!sendBE32(mClient, rcode)) { PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send rcode to uid " << uid; return; } Loading @@ -932,7 +929,7 @@ void DnsProxyListener::ResNSendHandler::run() { const int total_ip_addr_count = extractResNsendAnswers((uint8_t*) ansBuf.data(), nsendAns, rr_type, &ip_addrs); reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, arcode), event, rr_name, ip_addrs, resNSendToAiError(nsendAns, rcode), event, rr_name, ip_addrs, total_ip_addr_count); } } Loading getaddrinfo.cpp +21 −45 Original line number Diff line number Diff line Loading @@ -108,20 +108,13 @@ const Explore explore_options[] = { }; #define PTON_MAX 16 #define MAXPACKET (8 * 1024) typedef union { HEADER hdr; uint8_t buf[MAXPACKET]; } querybuf; struct res_target { struct res_target* next; const char* name; /* domain name */ int qclass, qtype; /* class and type of query */ uint8_t* answer; /* buffer to put answer */ int anslen; /* size of answer buffer */ int n; /* result length */ const char* name; // domain name int qclass, qtype; // class and type of query std::vector<uint8_t> answer = std::vector<uint8_t>(MAXPACKET, 0); // buffer to put answer int n = 0; // result length }; static int str2number(const char*); Loading @@ -139,8 +132,8 @@ static int get_port(const struct addrinfo*, const char*, int); static const struct afd* find_afd(int); static int ip6_str2scopeid(const char*, struct sockaddr_in6*, uint32_t*); static struct addrinfo* getanswer(const querybuf*, int, const char*, int, const struct addrinfo*, int* herrno); static struct addrinfo* getanswer(const std::vector<uint8_t>&, int, const char*, int, const struct addrinfo*, int* herrno); static int dns_getaddrinfo(const char* name, const addrinfo* pai, const android_net_context* netcontext, addrinfo** rv, NetworkDnsEventReported* event); Loading Loading @@ -838,8 +831,8 @@ static int ip6_str2scopeid(const char* scope, struct sockaddr_in6* sin6, uint32_ } \ } while (0) static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype, const struct addrinfo* pai, int* herrno) { static struct addrinfo* getanswer(const std::vector<uint8_t>& answer, int anslen, const char* qname, int qtype, const struct addrinfo* pai, int* herrno) { struct addrinfo sentinel = {}; struct addrinfo *cur; struct addrinfo ai; Loading @@ -856,14 +849,13 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char int (*name_ok)(const char*); char hostbuf[8 * 1024]; assert(answer != NULL); assert(qname != NULL); assert(pai != NULL); cur = &sentinel; canonname = NULL; eom = answer->buf + anslen; eom = answer.data() + anslen; switch (qtype) { case T_A: case T_AAAA: Loading @@ -876,18 +868,18 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char /* * find first satisfactory answer */ hp = &answer->hdr; hp = reinterpret_cast<const HEADER*>(answer.data()); ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; ep = hostbuf + sizeof hostbuf; cp = answer->buf; cp = answer.data(); BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { *herrno = NO_RECOVERY; return (NULL); } n = dn_expand(answer->buf, eom, cp, bp, ep - bp); n = dn_expand(answer.data(), eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { *herrno = NO_RECOVERY; return (NULL); Loading @@ -911,7 +903,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { n = dn_expand(answer->buf, eom, cp, bp, ep - bp); n = dn_expand(answer.data(), eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; Loading @@ -931,7 +923,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) { n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); n = dn_expand(answer.data(), eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { had_error++; continue; Loading Loading @@ -1397,16 +1389,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, res_target q = {}; res_target q2 = {}; auto buf = std::make_unique<querybuf>(); auto buf2 = std::make_unique<querybuf>(); switch (pai->ai_family) { case AF_UNSPEC: { /* prefer IPv6 */ q.name = name; q.qclass = C_IN; q.answer = buf->buf; q.anslen = sizeof(buf->buf); int query_ipv6 = 1, query_ipv4 = 1; if (pai->ai_flags & AI_ADDRCONFIG) { query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid); Loading @@ -1419,8 +1406,6 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, q2.name = name; q2.qclass = C_IN; q2.qtype = T_A; q2.answer = buf2->buf; q2.anslen = sizeof(buf2->buf); } } else if (query_ipv4) { q.qtype = T_A; Loading @@ -1433,15 +1418,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, q.name = name; q.qclass = C_IN; q.qtype = T_A; q.answer = buf->buf; q.anslen = sizeof(buf->buf); break; case AF_INET6: q.name = name; q.qclass = C_IN; q.qtype = T_AAAA; q.answer = buf->buf; q.anslen = sizeof(buf->buf); break; default: return EAI_FAMILY; Loading @@ -1460,13 +1441,13 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, addrinfo sentinel = {}; addrinfo* cur = &sentinel; addrinfo* ai = getanswer(buf.get(), q.n, q.name, q.qtype, pai, &he); addrinfo* ai = getanswer(q.answer, q.n, q.name, q.qtype, pai, &he); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } if (q.next) { ai = getanswer(buf2.get(), q2.n, q2.name, q2.qtype, pai, &he); ai = getanswer(q2.answer, q2.n, q2.name, q2.qtype, pai, &he); if (ai) cur->ai_next = ai; } if (sentinel.ai_next == NULL) { Loading Loading @@ -1578,7 +1559,6 @@ static bool files_getaddrinfo(const char* name, const addrinfo* pai, addrinfo** */ static int res_queryN(const char* name, res_target* target, res_state res, int* herrno) { uint8_t buf[MAXPACKET]; HEADER* hp; int n; struct res_target* t; int rcode; Loading @@ -1591,10 +1571,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int* ancount = 0; for (t = target; t; t = t->next) { uint8_t* answer; int anslen; hp = (HEADER*) (void*) t->answer; HEADER* hp = (HEADER*)(void*)t->answer.data(); bool retried = false; again: hp->rcode = NOERROR; /* default */ Loading @@ -1602,8 +1579,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int* /* make it easier... */ int cl = t->qclass; int type = t->qtype; answer = t->answer; anslen = t->anslen; const int anslen = t->answer.size(); LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")"; Loading @@ -1620,7 +1596,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int* return n; } n = res_nsend(res, buf, n, answer, anslen, &rcode, 0); 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. Loading Loading @@ -1689,7 +1665,7 @@ static int res_searchN(const char* name, res_target* target, res_state res, int* assert(name != NULL); assert(target != NULL); hp = (HEADER*) (void*) target->answer; /*XXX*/ hp = (HEADER*)(void*)target->answer.data(); errno = 0; *herrno = HOST_NOT_FOUND; /* default, if we never query */ Loading Loading @@ -1721,7 +1697,7 @@ static int res_searchN(const char* name, res_target* target, res_state res, int* * the domain stuff is tried. Will have a better * fix after thread pools are used. */ _resolv_populate_res_for_net(res); resolv_populate_res_for_net(res); for (const auto& domain : res->search_domains) { ret = res_querydomainN(name, domain.c_str(), target, res, herrno); Loading gethnamaddr.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -95,8 +95,6 @@ using android::net::NetworkDnsEventReported; #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) #define MAXPACKET (8 * 1024) constexpr int MAXADDRS = 35; typedef union { Loading res_cache.cpp +58 −79 Original line number Diff line number Diff line Loading @@ -61,10 +61,14 @@ #include "DnsStats.h" #include "res_debug.h" #include "resolv_private.h" #include "util.h" using android::base::StringAppendF; using android::net::DnsQueryEvent; using android::net::DnsStats; using android::net::PROTO_DOT; using android::net::PROTO_TCP; using android::net::PROTO_UDP; using android::netdutils::DumpWriter; using android::netdutils::IPSockAddr; Loading Loading @@ -936,7 +940,7 @@ struct resolv_cache_info { struct resolv_cache_info* next; int nscount; std::vector<std::string> nameservers; struct addrinfo* nsaddrinfo[MAXNS]; // TODO: Use struct sockaddr_storage. std::vector<IPSockAddr> nameserverSockAddrs; int revision_id; // # times the nameservers have been replaced res_params params; struct res_stats nsstats[MAXNS]; Loading Loading @@ -1563,6 +1567,21 @@ std::vector<std::string> filter_nameservers(const std::vector<std::string>& serv return res; } bool isValidServer(const std::string& server) { const addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, }; addrinfo* result = nullptr; if (int err = getaddrinfo_numeric(server.c_str(), "53", hints, &result); err != 0) { LOG(WARNING) << __func__ << ": getaddrinfo_numeric(" << server << ") = " << gai_strerror(err); return false; } freeaddrinfo(result); return true; } } // namespace int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& servers, Loading @@ -1574,24 +1593,11 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve // Parse the addresses before actually locking or changing any state, in case there is an error. // As a side effect this also reduces the time the lock is kept. // TODO: find a better way to replace addrinfo*, something like std::vector<SafeAddrinfo> addrinfo* nsaddrinfo[MAXNS]; for (int i = 0; i < numservers; i++) { // The addrinfo structures allocated here are freed in free_nameservers_locked(). const addrinfo hints = { .ai_flags = AI_NUMERICHOST, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, }; const int rt = getaddrinfo_numeric(nameservers[i].c_str(), "53", hints, &nsaddrinfo[i]); if (rt != 0) { for (int j = 0; j < i; j++) { freeaddrinfo(nsaddrinfo[j]); } LOG(INFO) << __func__ << ": getaddrinfo_numeric(" << nameservers[i] << ") = " << gai_strerror(rt); return -EINVAL; } std::vector<IPSockAddr> ipSockAddrs; ipSockAddrs.reserve(nameservers.size()); for (const auto& server : nameservers) { if (!isValidServer(server)) return -EINVAL; ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53)); } std::lock_guard guard(cache_mutex); Loading @@ -1607,10 +1613,10 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve free_nameservers_locked(cache_info); cache_info->nameservers = std::move(nameservers); for (int i = 0; i < numservers; i++) { cache_info->nsaddrinfo[i] = nsaddrinfo[i]; LOG(INFO) << __func__ << ": netid = " << netid << ", addr = " << cache_info->nameservers[i]; } cache_info->nameserverSockAddrs = std::move(ipSockAddrs); cache_info->nscount = numservers; } else { if (cache_info->params.max_samples != old_max_samples) { Loading @@ -1621,23 +1627,15 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve // under which servers are considered usable. res_cache_clear_stats_locked(cache_info); } for (int j = 0; j < numservers; j++) { freeaddrinfo(nsaddrinfo[j]); } } // Always update the search paths. Cache-flushing however is not necessary, // since the stored cache entries do contain the domain, not just the host name. cache_info->search_domains = filter_domains(domains); std::vector<IPSockAddr> serverSockAddrs; serverSockAddrs.reserve(cache_info->nameservers.size()); for (const auto& server : cache_info->nameservers) { serverSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53)); } if (!cache_info->dnsStats->setServers(serverSockAddrs, android::net::PROTO_TCP) || !cache_info->dnsStats->setServers(serverSockAddrs, android::net::PROTO_UDP)) { // Setup stats for cleartext dns servers. if (!cache_info->dnsStats->setServers(cache_info->nameserverSockAddrs, PROTO_TCP) || !cache_info->dnsStats->setServers(cache_info->nameserverSockAddrs, PROTO_UDP)) { LOG(WARNING) << __func__ << ": netid = " << netid << ", failed to set dns stats"; return -EINVAL; } Loading @@ -1659,45 +1657,39 @@ static bool resolv_is_nameservers_equal(const std::vector<std::string>& oldServe } static void free_nameservers_locked(resolv_cache_info* cache_info) { int i; for (i = 0; i < cache_info->nscount; i++) { cache_info->nameservers.clear(); if (cache_info->nsaddrinfo[i] != nullptr) { freeaddrinfo(cache_info->nsaddrinfo[i]); cache_info->nsaddrinfo[i] = nullptr; } } cache_info->nscount = 0; cache_info->nameservers.clear(); cache_info->nameserverSockAddrs.clear(); res_cache_clear_stats_locked(cache_info); } void _resolv_populate_res_for_net(res_state statp) { if (statp == NULL) { void resolv_populate_res_for_net(ResState* statp) { if (statp == nullptr) { return; } LOG(INFO) << __func__ << ": netid=" << statp->netid; std::lock_guard guard(cache_mutex); resolv_cache_info* info = find_cache_info_locked(statp->netid); if (info != NULL) { int nserv; struct addrinfo* ai; for (nserv = 0; nserv < MAXNS; nserv++) { ai = info->nsaddrinfo[nserv]; if (ai == NULL) { break; } if (info == nullptr) return; // TODO: Convert nsaddrs[] to c++ container and remove the size-checking. const int serverNum = std::min(MAXNS, static_cast<int>(info->nameserverSockAddrs.size())); for (int nserv = 0; nserv < serverNum; nserv++) { sockaddr_storage ss = info->nameserverSockAddrs.at(nserv); if ((size_t)ai->ai_addrlen <= sizeof(statp->nsaddrs[0])) { memcpy(&statp->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen); if (auto sockaddr_len = sockaddrSize(ss); sockaddr_len != 0) { memcpy(&statp->nsaddrs[nserv], &ss, sockaddr_len); } else { LOG(INFO) << __func__ << ": found too long addrlen"; LOG(WARNING) << __func__ << ": can't get sa_len from " << info->nameserverSockAddrs.at(nserv); } } statp->nscount = nserv; statp->nscount = serverNum; statp->search_domains = info->search_domains; } } /* Resolver reachability statistics. */ Loading Loading @@ -1745,31 +1737,18 @@ int android_net_res_stats_get_info_for_net(unsigned netid, int* nscount, return -1; } int i; for (i = 0; i < info->nscount; i++) { // Verify that the following assumptions are held, failure indicates corruption: // - getaddrinfo() may never return a sockaddr > sockaddr_storage // - all addresses are valid // - there is only one address per addrinfo thanks to numeric resolution int addrlen = info->nsaddrinfo[i]->ai_addrlen; if (addrlen < (int) sizeof(struct sockaddr) || addrlen > (int) sizeof(servers[0])) { LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_addrlen == " << addrlen; errno = EMSGSIZE; return -1; } if (info->nsaddrinfo[i]->ai_addr == NULL) { LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_addr == NULL"; errno = ENOENT; return -1; } if (info->nsaddrinfo[i]->ai_next != NULL) { LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_next != NULL"; errno = ENOTUNIQ; *nscount = info->nscount; // It shouldn't happen, but just in case of buffer overflow. if (info->nscount != static_cast<int>(info->nameserverSockAddrs.size())) { LOG(INFO) << __func__ << ": nscount " << info->nscount << " != " << info->nameserverSockAddrs.size(); errno = EFAULT; return -1; } } *nscount = info->nscount; for (i = 0; i < info->nscount; i++) { memcpy(&servers[i], info->nsaddrinfo[i]->ai_addr, info->nsaddrinfo[i]->ai_addrlen); servers[i] = info->nameserverSockAddrs.at(i); stats[i] = info->nsstats[i]; } Loading Loading
Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ cc_library { "res_query.cpp", "res_send.cpp", "res_stats.cpp", "util.cpp", "Dns64Configuration.cpp", "DnsProxyListener.cpp", "DnsResolver.cpp", Loading
DnsProxyListener.cpp +6 −9 Original line number Diff line number Diff line Loading @@ -74,10 +74,6 @@ namespace { // Limits the number of outstanding DNS queries by client UID. constexpr int MAX_QUERIES_PER_UID = 256; // Max packet size for answer, sync with getaddrinfo.c // TODO: switch to dynamically allocated buffers with std::vector constexpr int MAXPACKET = 8 * 1024; android::netdutils::OperationLimiter<uid_t> queryLimiter(MAX_QUERIES_PER_UID); void logArguments(int argc, char** argv) { Loading Loading @@ -886,12 +882,13 @@ void DnsProxyListener::ResNSendHandler::run() { // Send DNS query std::vector<uint8_t> ansBuf(MAXPACKET, 0); int arcode, nsendAns = -1; int rcode = ns_r_noerror; int nsendAns = -1; NetworkDnsEventReported event; initDnsEvent(&event); if (queryLimiter.start(uid)) { nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET, &arcode, static_cast<ResNsendFlags>(mFlags), &event); &rcode, static_cast<ResNsendFlags>(mFlags), &event); queryLimiter.finish(uid); } else { LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid Loading @@ -909,13 +906,13 @@ void DnsProxyListener::ResNSendHandler::run() { sendBE32(mClient, nsendAns); if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, arcode), event, rr_name); resNSendToAiError(nsendAns, rcode), event, rr_name); } return; } // Send rcode if (!sendBE32(mClient, arcode)) { if (!sendBE32(mClient, rcode)) { PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send rcode to uid " << uid; return; } Loading @@ -932,7 +929,7 @@ void DnsProxyListener::ResNSendHandler::run() { const int total_ip_addr_count = extractResNsendAnswers((uint8_t*) ansBuf.data(), nsendAns, rr_type, &ip_addrs); reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, arcode), event, rr_name, ip_addrs, resNSendToAiError(nsendAns, rcode), event, rr_name, ip_addrs, total_ip_addr_count); } } Loading
getaddrinfo.cpp +21 −45 Original line number Diff line number Diff line Loading @@ -108,20 +108,13 @@ const Explore explore_options[] = { }; #define PTON_MAX 16 #define MAXPACKET (8 * 1024) typedef union { HEADER hdr; uint8_t buf[MAXPACKET]; } querybuf; struct res_target { struct res_target* next; const char* name; /* domain name */ int qclass, qtype; /* class and type of query */ uint8_t* answer; /* buffer to put answer */ int anslen; /* size of answer buffer */ int n; /* result length */ const char* name; // domain name int qclass, qtype; // class and type of query std::vector<uint8_t> answer = std::vector<uint8_t>(MAXPACKET, 0); // buffer to put answer int n = 0; // result length }; static int str2number(const char*); Loading @@ -139,8 +132,8 @@ static int get_port(const struct addrinfo*, const char*, int); static const struct afd* find_afd(int); static int ip6_str2scopeid(const char*, struct sockaddr_in6*, uint32_t*); static struct addrinfo* getanswer(const querybuf*, int, const char*, int, const struct addrinfo*, int* herrno); static struct addrinfo* getanswer(const std::vector<uint8_t>&, int, const char*, int, const struct addrinfo*, int* herrno); static int dns_getaddrinfo(const char* name, const addrinfo* pai, const android_net_context* netcontext, addrinfo** rv, NetworkDnsEventReported* event); Loading Loading @@ -838,8 +831,8 @@ static int ip6_str2scopeid(const char* scope, struct sockaddr_in6* sin6, uint32_ } \ } while (0) static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype, const struct addrinfo* pai, int* herrno) { static struct addrinfo* getanswer(const std::vector<uint8_t>& answer, int anslen, const char* qname, int qtype, const struct addrinfo* pai, int* herrno) { struct addrinfo sentinel = {}; struct addrinfo *cur; struct addrinfo ai; Loading @@ -856,14 +849,13 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char int (*name_ok)(const char*); char hostbuf[8 * 1024]; assert(answer != NULL); assert(qname != NULL); assert(pai != NULL); cur = &sentinel; canonname = NULL; eom = answer->buf + anslen; eom = answer.data() + anslen; switch (qtype) { case T_A: case T_AAAA: Loading @@ -876,18 +868,18 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char /* * find first satisfactory answer */ hp = &answer->hdr; hp = reinterpret_cast<const HEADER*>(answer.data()); ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; ep = hostbuf + sizeof hostbuf; cp = answer->buf; cp = answer.data(); BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { *herrno = NO_RECOVERY; return (NULL); } n = dn_expand(answer->buf, eom, cp, bp, ep - bp); n = dn_expand(answer.data(), eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { *herrno = NO_RECOVERY; return (NULL); Loading @@ -911,7 +903,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { n = dn_expand(answer->buf, eom, cp, bp, ep - bp); n = dn_expand(answer.data(), eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; Loading @@ -931,7 +923,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) { n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); n = dn_expand(answer.data(), eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { had_error++; continue; Loading Loading @@ -1397,16 +1389,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, res_target q = {}; res_target q2 = {}; auto buf = std::make_unique<querybuf>(); auto buf2 = std::make_unique<querybuf>(); switch (pai->ai_family) { case AF_UNSPEC: { /* prefer IPv6 */ q.name = name; q.qclass = C_IN; q.answer = buf->buf; q.anslen = sizeof(buf->buf); int query_ipv6 = 1, query_ipv4 = 1; if (pai->ai_flags & AI_ADDRCONFIG) { query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid); Loading @@ -1419,8 +1406,6 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, q2.name = name; q2.qclass = C_IN; q2.qtype = T_A; q2.answer = buf2->buf; q2.anslen = sizeof(buf2->buf); } } else if (query_ipv4) { q.qtype = T_A; Loading @@ -1433,15 +1418,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, q.name = name; q.qclass = C_IN; q.qtype = T_A; q.answer = buf->buf; q.anslen = sizeof(buf->buf); break; case AF_INET6: q.name = name; q.qclass = C_IN; q.qtype = T_AAAA; q.answer = buf->buf; q.anslen = sizeof(buf->buf); break; default: return EAI_FAMILY; Loading @@ -1460,13 +1441,13 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai, addrinfo sentinel = {}; addrinfo* cur = &sentinel; addrinfo* ai = getanswer(buf.get(), q.n, q.name, q.qtype, pai, &he); addrinfo* ai = getanswer(q.answer, q.n, q.name, q.qtype, pai, &he); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } if (q.next) { ai = getanswer(buf2.get(), q2.n, q2.name, q2.qtype, pai, &he); ai = getanswer(q2.answer, q2.n, q2.name, q2.qtype, pai, &he); if (ai) cur->ai_next = ai; } if (sentinel.ai_next == NULL) { Loading Loading @@ -1578,7 +1559,6 @@ static bool files_getaddrinfo(const char* name, const addrinfo* pai, addrinfo** */ static int res_queryN(const char* name, res_target* target, res_state res, int* herrno) { uint8_t buf[MAXPACKET]; HEADER* hp; int n; struct res_target* t; int rcode; Loading @@ -1591,10 +1571,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int* ancount = 0; for (t = target; t; t = t->next) { uint8_t* answer; int anslen; hp = (HEADER*) (void*) t->answer; HEADER* hp = (HEADER*)(void*)t->answer.data(); bool retried = false; again: hp->rcode = NOERROR; /* default */ Loading @@ -1602,8 +1579,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int* /* make it easier... */ int cl = t->qclass; int type = t->qtype; answer = t->answer; anslen = t->anslen; const int anslen = t->answer.size(); LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")"; Loading @@ -1620,7 +1596,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int* return n; } n = res_nsend(res, buf, n, answer, anslen, &rcode, 0); 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. Loading Loading @@ -1689,7 +1665,7 @@ static int res_searchN(const char* name, res_target* target, res_state res, int* assert(name != NULL); assert(target != NULL); hp = (HEADER*) (void*) target->answer; /*XXX*/ hp = (HEADER*)(void*)target->answer.data(); errno = 0; *herrno = HOST_NOT_FOUND; /* default, if we never query */ Loading Loading @@ -1721,7 +1697,7 @@ static int res_searchN(const char* name, res_target* target, res_state res, int* * the domain stuff is tried. Will have a better * fix after thread pools are used. */ _resolv_populate_res_for_net(res); resolv_populate_res_for_net(res); for (const auto& domain : res->search_domains) { ret = res_querydomainN(name, domain.c_str(), target, res, herrno); Loading
gethnamaddr.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -95,8 +95,6 @@ using android::net::NetworkDnsEventReported; #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) #define MAXPACKET (8 * 1024) constexpr int MAXADDRS = 35; typedef union { Loading
res_cache.cpp +58 −79 Original line number Diff line number Diff line Loading @@ -61,10 +61,14 @@ #include "DnsStats.h" #include "res_debug.h" #include "resolv_private.h" #include "util.h" using android::base::StringAppendF; using android::net::DnsQueryEvent; using android::net::DnsStats; using android::net::PROTO_DOT; using android::net::PROTO_TCP; using android::net::PROTO_UDP; using android::netdutils::DumpWriter; using android::netdutils::IPSockAddr; Loading Loading @@ -936,7 +940,7 @@ struct resolv_cache_info { struct resolv_cache_info* next; int nscount; std::vector<std::string> nameservers; struct addrinfo* nsaddrinfo[MAXNS]; // TODO: Use struct sockaddr_storage. std::vector<IPSockAddr> nameserverSockAddrs; int revision_id; // # times the nameservers have been replaced res_params params; struct res_stats nsstats[MAXNS]; Loading Loading @@ -1563,6 +1567,21 @@ std::vector<std::string> filter_nameservers(const std::vector<std::string>& serv return res; } bool isValidServer(const std::string& server) { const addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, }; addrinfo* result = nullptr; if (int err = getaddrinfo_numeric(server.c_str(), "53", hints, &result); err != 0) { LOG(WARNING) << __func__ << ": getaddrinfo_numeric(" << server << ") = " << gai_strerror(err); return false; } freeaddrinfo(result); return true; } } // namespace int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& servers, Loading @@ -1574,24 +1593,11 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve // Parse the addresses before actually locking or changing any state, in case there is an error. // As a side effect this also reduces the time the lock is kept. // TODO: find a better way to replace addrinfo*, something like std::vector<SafeAddrinfo> addrinfo* nsaddrinfo[MAXNS]; for (int i = 0; i < numservers; i++) { // The addrinfo structures allocated here are freed in free_nameservers_locked(). const addrinfo hints = { .ai_flags = AI_NUMERICHOST, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, }; const int rt = getaddrinfo_numeric(nameservers[i].c_str(), "53", hints, &nsaddrinfo[i]); if (rt != 0) { for (int j = 0; j < i; j++) { freeaddrinfo(nsaddrinfo[j]); } LOG(INFO) << __func__ << ": getaddrinfo_numeric(" << nameservers[i] << ") = " << gai_strerror(rt); return -EINVAL; } std::vector<IPSockAddr> ipSockAddrs; ipSockAddrs.reserve(nameservers.size()); for (const auto& server : nameservers) { if (!isValidServer(server)) return -EINVAL; ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53)); } std::lock_guard guard(cache_mutex); Loading @@ -1607,10 +1613,10 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve free_nameservers_locked(cache_info); cache_info->nameservers = std::move(nameservers); for (int i = 0; i < numservers; i++) { cache_info->nsaddrinfo[i] = nsaddrinfo[i]; LOG(INFO) << __func__ << ": netid = " << netid << ", addr = " << cache_info->nameservers[i]; } cache_info->nameserverSockAddrs = std::move(ipSockAddrs); cache_info->nscount = numservers; } else { if (cache_info->params.max_samples != old_max_samples) { Loading @@ -1621,23 +1627,15 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve // under which servers are considered usable. res_cache_clear_stats_locked(cache_info); } for (int j = 0; j < numservers; j++) { freeaddrinfo(nsaddrinfo[j]); } } // Always update the search paths. Cache-flushing however is not necessary, // since the stored cache entries do contain the domain, not just the host name. cache_info->search_domains = filter_domains(domains); std::vector<IPSockAddr> serverSockAddrs; serverSockAddrs.reserve(cache_info->nameservers.size()); for (const auto& server : cache_info->nameservers) { serverSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53)); } if (!cache_info->dnsStats->setServers(serverSockAddrs, android::net::PROTO_TCP) || !cache_info->dnsStats->setServers(serverSockAddrs, android::net::PROTO_UDP)) { // Setup stats for cleartext dns servers. if (!cache_info->dnsStats->setServers(cache_info->nameserverSockAddrs, PROTO_TCP) || !cache_info->dnsStats->setServers(cache_info->nameserverSockAddrs, PROTO_UDP)) { LOG(WARNING) << __func__ << ": netid = " << netid << ", failed to set dns stats"; return -EINVAL; } Loading @@ -1659,45 +1657,39 @@ static bool resolv_is_nameservers_equal(const std::vector<std::string>& oldServe } static void free_nameservers_locked(resolv_cache_info* cache_info) { int i; for (i = 0; i < cache_info->nscount; i++) { cache_info->nameservers.clear(); if (cache_info->nsaddrinfo[i] != nullptr) { freeaddrinfo(cache_info->nsaddrinfo[i]); cache_info->nsaddrinfo[i] = nullptr; } } cache_info->nscount = 0; cache_info->nameservers.clear(); cache_info->nameserverSockAddrs.clear(); res_cache_clear_stats_locked(cache_info); } void _resolv_populate_res_for_net(res_state statp) { if (statp == NULL) { void resolv_populate_res_for_net(ResState* statp) { if (statp == nullptr) { return; } LOG(INFO) << __func__ << ": netid=" << statp->netid; std::lock_guard guard(cache_mutex); resolv_cache_info* info = find_cache_info_locked(statp->netid); if (info != NULL) { int nserv; struct addrinfo* ai; for (nserv = 0; nserv < MAXNS; nserv++) { ai = info->nsaddrinfo[nserv]; if (ai == NULL) { break; } if (info == nullptr) return; // TODO: Convert nsaddrs[] to c++ container and remove the size-checking. const int serverNum = std::min(MAXNS, static_cast<int>(info->nameserverSockAddrs.size())); for (int nserv = 0; nserv < serverNum; nserv++) { sockaddr_storage ss = info->nameserverSockAddrs.at(nserv); if ((size_t)ai->ai_addrlen <= sizeof(statp->nsaddrs[0])) { memcpy(&statp->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen); if (auto sockaddr_len = sockaddrSize(ss); sockaddr_len != 0) { memcpy(&statp->nsaddrs[nserv], &ss, sockaddr_len); } else { LOG(INFO) << __func__ << ": found too long addrlen"; LOG(WARNING) << __func__ << ": can't get sa_len from " << info->nameserverSockAddrs.at(nserv); } } statp->nscount = nserv; statp->nscount = serverNum; statp->search_domains = info->search_domains; } } /* Resolver reachability statistics. */ Loading Loading @@ -1745,31 +1737,18 @@ int android_net_res_stats_get_info_for_net(unsigned netid, int* nscount, return -1; } int i; for (i = 0; i < info->nscount; i++) { // Verify that the following assumptions are held, failure indicates corruption: // - getaddrinfo() may never return a sockaddr > sockaddr_storage // - all addresses are valid // - there is only one address per addrinfo thanks to numeric resolution int addrlen = info->nsaddrinfo[i]->ai_addrlen; if (addrlen < (int) sizeof(struct sockaddr) || addrlen > (int) sizeof(servers[0])) { LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_addrlen == " << addrlen; errno = EMSGSIZE; return -1; } if (info->nsaddrinfo[i]->ai_addr == NULL) { LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_addr == NULL"; errno = ENOENT; return -1; } if (info->nsaddrinfo[i]->ai_next != NULL) { LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_next != NULL"; errno = ENOTUNIQ; *nscount = info->nscount; // It shouldn't happen, but just in case of buffer overflow. if (info->nscount != static_cast<int>(info->nameserverSockAddrs.size())) { LOG(INFO) << __func__ << ": nscount " << info->nscount << " != " << info->nameserverSockAddrs.size(); errno = EFAULT; return -1; } } *nscount = info->nscount; for (i = 0; i < info->nscount; i++) { memcpy(&servers[i], info->nsaddrinfo[i]->ai_addr, info->nsaddrinfo[i]->ai_addrlen); servers[i] = info->nameserverSockAddrs.at(i); stats[i] = info->nsstats[i]; } Loading