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 getaddrinfo.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -1697,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 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 res_init.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ void res_init(ResState* statp, const struct android_net_context* _Nonnull netcon } // The following dummy initialization is probably useless because // it's overwritten later by _resolv_populate_res_for_net(). // it's overwritten later by resolv_populate_res_for_net(). // TODO: check if it's safe to remove. const sockaddr_union u{ .sin.sin_addr.s_addr = INADDR_ANY, Loading res_query.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -250,7 +250,7 @@ int res_nsearch(res_state statp, const char* name, /* domain name */ * be loaded once for the thread instead of each * time a query is tried. */ _resolv_populate_res_for_net(statp); resolv_populate_res_for_net(statp); for (const auto& domain : statp->search_domains) { if (domain == "." || domain == "") ++root_on_list; 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
getaddrinfo.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -1697,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
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
res_init.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ void res_init(ResState* statp, const struct android_net_context* _Nonnull netcon } // The following dummy initialization is probably useless because // it's overwritten later by _resolv_populate_res_for_net(). // it's overwritten later by resolv_populate_res_for_net(). // TODO: check if it's safe to remove. const sockaddr_union u{ .sin.sin_addr.s_addr = INADDR_ANY, Loading
res_query.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -250,7 +250,7 @@ int res_nsearch(res_state statp, const char* name, /* domain name */ * be loaded once for the thread instead of each * time a query is tried. */ _resolv_populate_res_for_net(statp); resolv_populate_res_for_net(statp); for (const auto& domain : statp->search_domains) { if (domain == "." || domain == "") ++root_on_list; Loading