Home | History | Annotate | Download | only in dhcp
      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/dhcp/dhcp_provider.h"
     18 
     19 #include <signal.h>
     20 
     21 #include <base/bind.h>
     22 #include <base/files/file_util.h>
     23 #include <base/process/process.h>
     24 #include <base/process/process_iterator.h>
     25 #include <base/stl_util.h>
     26 #include <base/strings/stringprintf.h>
     27 
     28 #include "shill/control_interface.h"
     29 #include "shill/dhcp/dhcpcd_listener_interface.h"
     30 #include "shill/dhcp/dhcpv4_config.h"
     31 #ifndef DISABLE_DHCPV6
     32 #include "shill/dhcp/dhcpv6_config.h"
     33 #endif
     34 #include "shill/dhcp_properties.h"
     35 #include "shill/event_dispatcher.h"
     36 #include "shill/logging.h"
     37 
     38 using base::FilePath;
     39 using std::string;
     40 
     41 namespace shill {
     42 
     43 namespace Logging {
     44 static auto kModuleLogScope = ScopeLogger::kDHCP;
     45 static string ObjectID(DHCPProvider* d) { return "(dhcp_provider)"; }
     46 }
     47 
     48 namespace {
     49 base::LazyInstance<DHCPProvider> g_dhcp_provider = LAZY_INSTANCE_INITIALIZER;
     50 static const int kUnbindDelayMilliseconds = 2000;
     51 
     52 #if defined(__ANDROID__)
     53 const char kDHCPCDExecutableName[] = "dhcpcd-6.8.2";
     54 #else
     55 const char kDHCPCDExecutableName[] = "dhcpcd";
     56 #endif  // __ANDROID__
     57 
     58 }  // namespace
     59 
     60 constexpr char DHCPProvider::kDHCPCDPathFormatLease[];
     61 #ifndef DISABLE_DHCPV6
     62 constexpr char DHCPProvider::kDHCPCDPathFormatLease6[];
     63 #endif  // DISABLE_DHCPV6
     64 
     65 DHCPProvider::DHCPProvider()
     66     : root_("/"),
     67       control_interface_(nullptr),
     68       dispatcher_(nullptr),
     69       metrics_(nullptr) {
     70   SLOG(this, 2) << __func__;
     71 }
     72 
     73 DHCPProvider::~DHCPProvider() {
     74   SLOG(this, 2) << __func__;
     75 }
     76 
     77 DHCPProvider* DHCPProvider::GetInstance() {
     78   return g_dhcp_provider.Pointer();
     79 }
     80 
     81 void DHCPProvider::Init(ControlInterface* control_interface,
     82                         EventDispatcher* dispatcher,
     83                         Metrics* metrics) {
     84   SLOG(this, 2) << __func__;
     85   listener_.reset(control_interface->CreateDHCPCDListener(this));
     86   control_interface_ = control_interface;
     87   dispatcher_ = dispatcher;
     88   metrics_ = metrics;
     89 
     90   // Kill the dhcpcd processes accidentally left by previous run.
     91   base::NamedProcessIterator iter(kDHCPCDExecutableName, NULL);
     92   while (const base::ProcessEntry* entry = iter.NextProcessEntry()) {
     93     base::Process process = base::Process::Open(entry->pid());
     94     kill(process.Pid(),SIGKILL);
     95   }
     96 }
     97 
     98 void DHCPProvider::Stop() {
     99   listener_.reset();
    100 }
    101 
    102 DHCPConfigRefPtr DHCPProvider::CreateIPv4Config(
    103     const string& device_name,
    104     const string& lease_file_suffix,
    105     bool arp_gateway,
    106     const DhcpProperties& dhcp_props) {
    107   SLOG(this, 2) << __func__ << " device: " << device_name;
    108   return new DHCPv4Config(control_interface_,
    109                           dispatcher_,
    110                           this,
    111                           device_name,
    112                           lease_file_suffix,
    113                           arp_gateway,
    114                           dhcp_props,
    115                           metrics_);
    116 }
    117 
    118 #ifndef DISABLE_DHCPV6
    119 DHCPConfigRefPtr DHCPProvider::CreateIPv6Config(
    120     const string& device_name, const string& lease_file_suffix) {
    121   SLOG(this, 2) << __func__ << " device: " << device_name;
    122   return new DHCPv6Config(control_interface_,
    123                           dispatcher_,
    124                           this,
    125                           device_name,
    126                           lease_file_suffix);
    127 }
    128 #endif
    129 
    130 DHCPConfigRefPtr DHCPProvider::GetConfig(int pid) {
    131   SLOG(this, 2) << __func__ << " pid: " << pid;
    132   PIDConfigMap::const_iterator it = configs_.find(pid);
    133   if (it == configs_.end()) {
    134     return nullptr;
    135   }
    136   return it->second;
    137 }
    138 
    139 void DHCPProvider::BindPID(int pid, const DHCPConfigRefPtr& config) {
    140   SLOG(this, 2) << __func__ << " pid: " << pid;
    141   configs_[pid] = config;
    142 }
    143 
    144 void DHCPProvider::UnbindPID(int pid) {
    145   SLOG(this, 2) << __func__ << " pid: " << pid;
    146   configs_.erase(pid);
    147   recently_unbound_pids_.insert(pid);
    148   dispatcher_->PostDelayedTask(base::Bind(&DHCPProvider::RetireUnboundPID,
    149                                           base::Unretained(this),
    150                                           pid), kUnbindDelayMilliseconds);
    151 }
    152 
    153 void DHCPProvider::RetireUnboundPID(int pid) {
    154   recently_unbound_pids_.erase(pid);
    155 }
    156 
    157 bool DHCPProvider::IsRecentlyUnbound(int pid) {
    158   return ContainsValue(recently_unbound_pids_, pid);
    159 }
    160 
    161 void DHCPProvider::DestroyLease(const string& name) {
    162   SLOG(this, 2) << __func__ << " name: " << name;
    163   base::DeleteFile(root_.Append(
    164       base::StringPrintf(kDHCPCDPathFormatLease,
    165                          name.c_str())), false);
    166 #ifndef DISABLE_DHCPV6
    167   base::DeleteFile(root_.Append(
    168       base::StringPrintf(kDHCPCDPathFormatLease6,
    169                          name.c_str())), false);
    170 #endif  // DISABLE_DHCPV6
    171 }
    172 
    173 }  // namespace shill
    174