summaryrefslogtreecommitdiff
path: root/resolv/res_cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/res_cache.cpp')
-rw-r--r--resolv/res_cache.cpp94
1 files changed, 42 insertions, 52 deletions
diff --git a/resolv/res_cache.cpp b/resolv/res_cache.cpp
index abf90110..befcbed8 100644
--- a/resolv/res_cache.cpp
+++ b/resolv/res_cache.cpp
@@ -35,7 +35,10 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <algorithm>
#include <mutex>
+#include <set>
+#include <vector>
#include <arpa/inet.h>
#include <arpa/nameser.h>
@@ -46,6 +49,7 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/strings.h>
#include <android-base/thread_annotations.h>
#include <android/multinetwork.h> // ResNsendFlags
@@ -1142,8 +1146,7 @@ struct resolv_cache_info {
int revision_id; // # times the nameservers have been replaced
res_params params;
struct res_stats nsstats[MAXNS];
- char defdname[MAXDNSRCHPATH];
- int dnsrch_offset[MAXDNSRCH + 1]; // offsets into defdname
+ std::vector<std::string> search_domains;
int wait_for_pending_req_timeout_count;
};
@@ -1719,12 +1722,35 @@ static void resolv_set_experiment_params(res_params* params) {
}
}
-int resolv_set_nameservers_for_net(unsigned netid, const char** servers, const int numservers,
- const char* domains, const res_params* params) {
- char* cp;
- int* offset;
- struct addrinfo* nsaddrinfo[MAXNS];
+int resolv_set_nameservers(unsigned netid, const char** servers, int numservers,
+ const char* domains, const res_params* params) {
+ return resolv_set_nameservers(netid, servers, numservers, android::base::Split(domains, " "),
+ params);
+}
+
+namespace {
+// Returns valid domains without duplicates which are limited to max size |MAXDNSRCH|.
+std::vector<std::string> filter_domains(const std::vector<std::string>& domains) {
+ std::set<std::string> tmp_set;
+ std::vector<std::string> res;
+
+ std::copy_if(domains.begin(), domains.end(), std::back_inserter(res),
+ [&tmp_set](const std::string& str) {
+ return !(str.size() > MAXDNSRCHPATH - 1) && (tmp_set.insert(str).second);
+ });
+ if (res.size() > MAXDNSRCH) {
+ LOG(WARNING) << __func__ << ": valid domains=" << res.size()
+ << ", but MAXDNSRCH=" << MAXDNSRCH;
+ res.resize(MAXDNSRCH);
+ }
+ return res;
+}
+
+} // namespace
+
+int resolv_set_nameservers(unsigned netid, const char** servers, int numservers,
+ const std::vector<std::string>& domains, const res_params* params) {
if (numservers > MAXNS) {
LOG(ERROR) << __func__ << ": numservers=" << numservers << ", MAXNS=" << MAXNS;
return E2BIG;
@@ -1732,6 +1758,8 @@ int resolv_set_nameservers_for_net(unsigned netid, const char** servers, const i
// 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];
char sbuf[NI_MAXSERV];
snprintf(sbuf, sizeof(sbuf), "%u", NAMESERVER_PORT);
for (int i = 0; i < numservers; i++) {
@@ -1795,31 +1823,9 @@ int resolv_set_nameservers_for_net(unsigned netid, const char** servers, const i
}
}
- // Always update the search paths, since determining whether they actually changed is
- // complex due to the zero-padding, and probably not worth the effort. Cache-flushing
- // however is not necessary, since the stored cache entries do contain the domain, not
- // just the host name.
- strlcpy(cache_info->defdname, domains, sizeof(cache_info->defdname));
- if ((cp = strchr(cache_info->defdname, '\n')) != NULL) *cp = '\0';
- LOG(INFO) << __func__ << ": domains=\"" << cache_info->defdname << "\"";
-
- cp = cache_info->defdname;
- offset = cache_info->dnsrch_offset;
- while (offset < cache_info->dnsrch_offset + MAXDNSRCH) {
- while (*cp == ' ' || *cp == '\t') /* skip leading white space */
- cp++;
- if (*cp == '\0') /* stop if nothing more to do */
- break;
- *offset++ = cp - cache_info->defdname; /* record this search domain */
- while (*cp) { /* zero-terminate it */
- if (*cp == ' ' || *cp == '\t') {
- *cp++ = '\0';
- break;
- }
- cp++;
- }
- }
- *offset = -1; /* cache_info->dnsrch_offset has MAXDNSRCH+1 items */
+ // 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);
return 0;
}
@@ -1899,15 +1905,7 @@ void _resolv_populate_res_for_net(res_state statp) {
}
}
statp->nscount = nserv;
- // now do search domains. Note that we cache the offsets as this code runs alot
- // but the setting/offset-computer only runs when set/changed
- // WARNING: Don't use str*cpy() here, this string contains zeroes.
- memcpy(statp->defdname, info->defdname, sizeof(statp->defdname));
- char** pp = statp->dnsrch;
- int* p = info->dnsrch_offset;
- while (pp < statp->dnsrch + MAXDNSRCH && *p != -1) {
- *pp++ = &statp->defdname[0] + *p++;
- }
+ statp->search_domains = info->search_domains;
}
}
@@ -1979,17 +1977,9 @@ int android_net_res_stats_get_info_for_net(unsigned netid, int* nscount,
memcpy(&servers[i], info->nsaddrinfo[i]->ai_addr, info->nsaddrinfo[i]->ai_addrlen);
stats[i] = info->nsstats[i];
}
- for (i = 0; i < MAXDNSRCH; i++) {
- const char* cur_domain = info->defdname + info->dnsrch_offset[i];
- // dnsrch_offset[i] can either be -1 or point to an empty string to indicate the end
- // of the search offsets. Checking for < 0 is not strictly necessary, but safer.
- // TODO: Pass in a search domain array instead of a string to
- // resolv_set_nameservers_for_net() and make this double check unnecessary.
- if (info->dnsrch_offset[i] < 0 ||
- ((size_t) info->dnsrch_offset[i]) >= sizeof(info->defdname) || !cur_domain[0]) {
- break;
- }
- strlcpy(domains[i], cur_domain, MAXDNSRCHPATH);
+
+ for (i = 0; i < static_cast<int>(info->search_domains.size()); i++) {
+ strlcpy(domains[i], info->search_domains[i].c_str(), MAXDNSRCHPATH);
}
*dcount = i;
*params = info->params;