Home | History | Annotate | Download | only in shill
      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;
     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 
     47 Resolver::Resolver() {}
     48 
     49 Resolver::~Resolver() {}
     50 
     51 Resolver* Resolver::GetInstance() {
     52   return g_resolver.Pointer();
     53 }
     54 
     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 
    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