| // |
| // 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 |