// // Copyright (C) 2015 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "shill/dns_server_proxy.h" #include <map> #include <base/bind.h> #include <base/strings/stringprintf.h> #include "shill/logging.h" #include "shill/process_manager.h" using std::string; using std::vector; namespace shill { namespace { const char kDnsmasqPath[] = "/system/bin/dnsmasq"; const char kDnsmasqPidFilePath[] = "/data/misc/shill/dnsmasq.pid"; const char kDnsmasqUser[] = "system"; const char kDnsmasqGroup[] = "system"; const int kInvalidPID = -1; } DNSServerProxy::DNSServerProxy(const vector<string>& dns_servers) : process_manager_(ProcessManager::GetInstance()), pid_(kInvalidPID), dns_servers_(dns_servers) {} DNSServerProxy::~DNSServerProxy() { if (pid_ != kInvalidPID) { Stop(); } } bool DNSServerProxy::Start() { if (pid_ != kInvalidPID) { LOG(ERROR) << __func__ << ": already started"; return false; } // Setup command line arguments for dnsmasq. vector<string> args; args.push_back("--no-hosts"); args.push_back("--listen-address=127.0.0.1"); args.push_back("--no-resolv"); args.push_back("--keep-in-foreground"); args.push_back(base::StringPrintf("--user=%s", kDnsmasqUser)); args.push_back(base::StringPrintf("--group=%s", kDnsmasqGroup)); for (const auto& server : dns_servers_) { args.push_back(base::StringPrintf("--server=%s", server.c_str())); } args.push_back(base::StringPrintf("--pid-file=%s", kDnsmasqPidFilePath)); // Start dnsmasq. // TODO(zqiu): start dnsmasq with Minijail when the latter is working on // Android (b/24572800). pid_t pid = process_manager_->StartProcess( FROM_HERE, base::FilePath(kDnsmasqPath), args, std::map<string, string>(), // No environment variables needed. true, // Terminate with parent. base::Bind(&DNSServerProxy::OnProcessExited, weak_factory_.GetWeakPtr())); if (pid < 0) { return false; } pid_ = pid; LOG(INFO) << "Spawned " << kDnsmasqPath << " with pid: " << pid_; return true; } void DNSServerProxy::Stop() { if (pid_ == kInvalidPID) { LOG(ERROR) << __func__ << ": already stopped"; return; } process_manager_->StopProcess(pid_); } void DNSServerProxy::OnProcessExited(int exit_status) { CHECK(pid_); if (exit_status != EXIT_SUCCESS) { LOG(WARNING) << "pid " << pid_ << " exit status " << exit_status; } pid_ = kInvalidPID; } } // namespace shill