1// 2// Copyright (C) 2015 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/dns_server_proxy.h" 18 19#include <map> 20 21#include <base/bind.h> 22#include <base/strings/stringprintf.h> 23 24#include "shill/logging.h" 25#include "shill/process_manager.h" 26 27using std::string; 28using std::vector; 29 30namespace shill { 31 32namespace { 33const char kDnsmasqPath[] = "/system/bin/dnsmasq"; 34const char kDnsmasqPidFilePath[] = "/data/misc/shill/dnsmasq.pid"; 35const char kDnsmasqUser[] = "system"; 36const char kDnsmasqGroup[] = "system"; 37const int kInvalidPID = -1; 38} 39 40DNSServerProxy::DNSServerProxy(const vector<string>& dns_servers) 41 : process_manager_(ProcessManager::GetInstance()), 42 pid_(kInvalidPID), 43 dns_servers_(dns_servers) {} 44 45DNSServerProxy::~DNSServerProxy() { 46 if (pid_ != kInvalidPID) { 47 Stop(); 48 } 49} 50 51bool DNSServerProxy::Start() { 52 if (pid_ != kInvalidPID) { 53 LOG(ERROR) << __func__ << ": already started"; 54 return false; 55 } 56 // Setup command line arguments for dnsmasq. 57 vector<string> args; 58 args.push_back("--no-hosts"); 59 args.push_back("--listen-address=127.0.0.1"); 60 args.push_back("--no-resolv"); 61 args.push_back("--keep-in-foreground"); 62 args.push_back(base::StringPrintf("--user=%s", kDnsmasqUser)); 63 args.push_back(base::StringPrintf("--group=%s", kDnsmasqGroup)); 64 for (const auto& server : dns_servers_) { 65 args.push_back(base::StringPrintf("--server=%s", server.c_str())); 66 } 67 args.push_back(base::StringPrintf("--pid-file=%s", kDnsmasqPidFilePath)); 68 // Start dnsmasq. 69 // TODO(zqiu): start dnsmasq with Minijail when the latter is working on 70 // Android (b/24572800). 71 pid_t pid = 72 process_manager_->StartProcess( 73 FROM_HERE, 74 base::FilePath(kDnsmasqPath), 75 args, 76 std::map<string, string>(), // No environment variables needed. 77 true, // Terminate with parent. 78 base::Bind(&DNSServerProxy::OnProcessExited, 79 weak_factory_.GetWeakPtr())); 80 if (pid < 0) { 81 return false; 82 } 83 84 pid_ = pid; 85 LOG(INFO) << "Spawned " << kDnsmasqPath << " with pid: " << pid_; 86 return true; 87} 88 89void DNSServerProxy::Stop() { 90 if (pid_ == kInvalidPID) { 91 LOG(ERROR) << __func__ << ": already stopped"; 92 return; 93 } 94 process_manager_->StopProcess(pid_); 95} 96 97void DNSServerProxy::OnProcessExited(int exit_status) { 98 CHECK(pid_); 99 if (exit_status != EXIT_SUCCESS) { 100 LOG(WARNING) << "pid " << pid_ << " exit status " << exit_status; 101 } 102 pid_ = kInvalidPID; 103} 104 105} // namespace shill 106