1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/resolver.h"
18
19 #include <algorithm>
20 #include <string>
21 #include <vector>
22
23 #include <base/files/file_util.h>
24 #include <base/strings/string_util.h>
25 #include <base/strings/stringprintf.h>
26
27 #include "shill/ipconfig.h"
28 #include "shill/logging.h"
29
30 using base::StringPrintf;
31 using std::string;
32 using std::vector;
33
34 namespace shill {
35
36 namespace Logging {
37 static auto kModuleLogScope = ScopeLogger::kResolver;
ObjectID(Resolver * r)38 static string ObjectID(Resolver* r) { return "(resolver)"; }
39 }
40
41 namespace {
42 base::LazyInstance<Resolver> g_resolver = LAZY_INSTANCE_INITIALIZER;
43 } // namespace
44
45 const char Resolver::kDefaultIgnoredSearchList[] = "gateway.2wire.net";
46
Resolver()47 Resolver::Resolver() {}
48
~Resolver()49 Resolver::~Resolver() {}
50
GetInstance()51 Resolver* Resolver::GetInstance() {
52 return g_resolver.Pointer();
53 }
54
SetDNSFromLists(const std::vector<std::string> & dns_servers,const std::vector<std::string> & domain_search)55 bool Resolver::SetDNSFromLists(const std::vector<std::string>& dns_servers,
56 const std::vector<std::string>& domain_search) {
57 SLOG(this, 2) << __func__;
58
59 if (dns_servers.empty() && domain_search.empty()) {
60 SLOG(this, 2) << "DNS list is empty";
61 return ClearDNS();
62 }
63
64 vector<string> lines;
65 vector<string>::const_iterator iter;
66 for (iter = dns_servers.begin();
67 iter != dns_servers.end(); ++iter) {
68 lines.push_back("nameserver " + *iter);
69 }
70
71 vector<string> filtered_domain_search;
72 for (iter = domain_search.begin();
73 iter != domain_search.end(); ++iter) {
74 if (std::find(ignored_search_list_.begin(),
75 ignored_search_list_.end(),
76 *iter) == ignored_search_list_.end()) {
77 filtered_domain_search.push_back(*iter);
78 }
79 }
80
81 if (!filtered_domain_search.empty()) {
82 lines.push_back("search " + base::JoinString(filtered_domain_search, " "));
83 }
84
85 // - Send queries one-at-a-time, rather than parallelizing IPv4
86 // and IPv6 queries for a single host.
87 // - Override the default 5-second request timeout and use a
88 // 1-second timeout instead. (NOTE: Chrome's ADNS will use
89 // one second, regardless of what we put here.)
90 // - Allow 5 attempts, rather than the default of 2.
91 // - For glibc, the worst case number of queries will be
92 // attempts * count(servers) * (count(search domains)+1)
93 // - For Chrome, the worst case number of queries will be
94 // attempts * count(servers) + 3 * glibc
95 // See crbug.com/224756 for supporting data.
96 lines.push_back("options single-request timeout:1 attempts:5");
97
98 // Newline at end of file
99 lines.push_back("");
100
101 string contents = base::JoinString(lines, "\n");
102
103 SLOG(this, 2) << "Writing DNS out to " << path_.value();
104 int count = base::WriteFile(path_, contents.c_str(), contents.size());
105
106 return count == static_cast<int>(contents.size());
107 }
108
ClearDNS()109 bool Resolver::ClearDNS() {
110 SLOG(this, 2) << __func__;
111
112 CHECK(!path_.empty());
113
114 return base::DeleteFile(path_, false);
115 }
116
117 } // namespace shill
118