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