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 #ifndef SHILL_DHCP_DHCP_CONFIG_H_
     18 #define SHILL_DHCP_DHCP_CONFIG_H_
     19 
     20 #include <map>
     21 #include <memory>
     22 #include <string>
     23 #include <vector>
     24 
     25 #include <base/cancelable_callback.h>
     26 #include <base/files/file_path.h>
     27 #include <base/memory/weak_ptr.h>
     28 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
     29 
     30 #include "shill/ipconfig.h"
     31 #include "shill/key_value_store.h"
     32 
     33 namespace shill {
     34 
     35 class ControlInterface;
     36 class DHCPProvider;
     37 class DHCPProxyInterface;
     38 class EventDispatcher;
     39 class Metrics;
     40 class ProcessManager;
     41 
     42 // This class provides a DHCP client instance for the device |device_name|.
     43 //
     44 // The DHPCConfig instance asks the DHCP client to create a lease file
     45 // containing the name |lease_file_suffix|.  If this suffix is the same as
     46 // |device_name|, the lease is considered to be ephemeral, and the lease
     47 // file is removed whenever this DHCPConfig instance is no longer needed.
     48 // Otherwise, the lease file persists and will be re-used in future attempts.
     49 class DHCPConfig : public IPConfig {
     50  public:
     51   DHCPConfig(ControlInterface* control_interface,
     52              EventDispatcher* dispatcher,
     53              DHCPProvider* provider,
     54              const std::string& device_name,
     55              const std::string& type,
     56              const std::string& lease_file_suffix);
     57   ~DHCPConfig() override;
     58 
     59   // Inherited from IPConfig.
     60   bool RequestIP() override;
     61   bool RenewIP() override;
     62   bool ReleaseIP(ReleaseReason reason) override;
     63 
     64   // If |proxy_| is not initialized already, sets it to a new D-Bus proxy to
     65   // |service|.
     66   void InitProxy(const std::string& service);
     67 
     68   // Processes an Event signal from dhcpcd.
     69   virtual void ProcessEventSignal(const std::string& reason,
     70                                   const KeyValueStore& configuration) = 0;
     71 
     72   // Processes an Status Change signal from dhcpcd.
     73   virtual void ProcessStatusChangeSignal(const std::string& status) = 0;
     74 
     75   // Set the minimum MTU that this configuration will respect.
     76   virtual void set_minimum_mtu(const int minimum_mtu) {
     77     minimum_mtu_ = minimum_mtu;
     78   }
     79 
     80  protected:
     81   // Overrides base clase implementation.
     82   void UpdateProperties(const Properties& properties,
     83                         bool new_lease_acquired) override;
     84   void NotifyFailure() override;
     85 
     86   int minimum_mtu() const { return minimum_mtu_; }
     87 
     88   void set_is_lease_active(bool active) { is_lease_active_ = active; }
     89 
     90   // Return true if the lease file is ephermeral, which means the lease file
     91   // should be deleted during cleanup.
     92   bool IsEphemeralLease() const;
     93 
     94   // Cleans up remaining state from a running client, if any, including freeing
     95   // its GPid, exit watch callback, and state files.
     96   // The file path for the lease file and pid file is different for IPv4
     97   // and IPv6. So make this function virtual to have the derived class delete
     98   // the files accordingly.
     99   virtual void CleanupClientState();
    100 
    101   // Return true if we should treat acquisition timeout as failure.
    102   virtual bool ShouldFailOnAcquisitionTimeout() { return true; }
    103 
    104   // Return true if we should keep the lease on disconnect.
    105   virtual bool ShouldKeepLeaseOnDisconnect() { return false; }
    106 
    107   // Return the list of flags used to start dhcpcd.
    108   virtual std::vector<std::string> GetFlags();
    109 
    110   base::FilePath root() const { return root_; }
    111 
    112  private:
    113   friend class DHCPConfigTest;
    114   friend class DHCPv4ConfigTest;
    115   friend class DHCPv6ConfigTest;
    116   FRIEND_TEST(DHCPConfigCallbackTest, NotifyFailure);
    117   FRIEND_TEST(DHCPConfigCallbackTest, ProcessAcquisitionTimeout);
    118   FRIEND_TEST(DHCPConfigCallbackTest, RequestIPTimeout);
    119   FRIEND_TEST(DHCPConfigCallbackTest, StartTimeout);
    120   FRIEND_TEST(DHCPConfigCallbackTest, StoppedDuringFailureCallback);
    121   FRIEND_TEST(DHCPConfigCallbackTest, StoppedDuringSuccessCallback);
    122   FRIEND_TEST(DHCPConfigTest, InitProxy);
    123   FRIEND_TEST(DHCPConfigTest, KeepLeaseOnDisconnect);
    124   FRIEND_TEST(DHCPConfigTest, ReleaseIP);
    125   FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithLease);
    126   FRIEND_TEST(DHCPConfigTest, ReleaseIPStaticIPWithoutLease);
    127   FRIEND_TEST(DHCPConfigTest, ReleaseLeaseOnDisconnect);
    128   FRIEND_TEST(DHCPConfigTest, RenewIP);
    129   FRIEND_TEST(DHCPConfigTest, RequestIP);
    130   FRIEND_TEST(DHCPConfigTest, Restart);
    131   FRIEND_TEST(DHCPConfigTest, RestartNoClient);
    132   FRIEND_TEST(DHCPConfigTest, StartFail);
    133   FRIEND_TEST(DHCPConfigTest, StartWithoutLeaseSuffix);
    134   FRIEND_TEST(DHCPConfigTest, Stop);
    135   FRIEND_TEST(DHCPConfigTest, StopDuringRequestIP);
    136   FRIEND_TEST(DHCPProviderTest, CreateIPv4Config);
    137 
    138   static const int kAcquisitionTimeoutSeconds;
    139 
    140   static const int kDHCPCDExitPollMilliseconds;
    141   static const int kDHCPCDExitWaitMilliseconds;
    142   static const char kDHCPCDPath[];
    143   static const char kDHCPCDUser[];
    144   static const char kDHCPCDGroup[];
    145 
    146   // Starts dhcpcd, returns true on success and false otherwise.
    147   bool Start();
    148 
    149   // Stops dhcpcd if running.
    150   void Stop(const char* reason);
    151 
    152   // Stops dhcpcd if already running and then starts it. Returns true on success
    153   // and false otherwise.
    154   bool Restart();
    155 
    156   // Called when the dhcpcd client process exits.
    157   void OnProcessExited(int exit_status);
    158 
    159   // Initialize a callback that will invoke ProcessAcquisitionTimeout if we
    160   // do not get a lease in a reasonable amount of time.
    161   void StartAcquisitionTimeout();
    162   // Cancel callback created by StartAcquisitionTimeout. One-liner included
    163   // for symmetry.
    164   void StopAcquisitionTimeout();
    165   // Called if we do not get a DHCP lease in a reasonable amount of time.
    166   // Informs upper layers of the failure.
    167   void ProcessAcquisitionTimeout();
    168 
    169   // Initialize a callback that will invoke ProcessExpirationTimeout if we
    170   // do not renew a lease in a |lease_duration_seconds|.
    171   void StartExpirationTimeout(uint32_t lease_duration_seconds);
    172   // Cancel callback created by StartExpirationTimeout. One-liner included
    173   // for symmetry.
    174   void StopExpirationTimeout();
    175   // Called if we do not renew a DHCP lease by the time the lease expires.
    176   // Informs upper layers of the expiration and restarts the DHCP client.
    177   void ProcessExpirationTimeout();
    178 
    179   // Kills DHCP client process.
    180   void KillClient();
    181 
    182   ControlInterface* control_interface_;
    183 
    184   DHCPProvider* provider_;
    185 
    186   // DHCP lease file suffix, used to differentiate the lease of one interface
    187   // or network from another.
    188   std::string lease_file_suffix_;
    189 
    190   // The PID of the spawned DHCP client. May be 0 if no client has been spawned
    191   // yet or the client has died.
    192   int pid_;
    193 
    194   // Whether a lease has been acquired from the DHCP server or gateway ARP.
    195   bool is_lease_active_;
    196 
    197   // The proxy for communicating with the DHCP client.
    198   std::unique_ptr<DHCPProxyInterface> proxy_;
    199 
    200   // Called if we fail to get a DHCP lease in a timely manner.
    201   base::CancelableClosure lease_acquisition_timeout_callback_;
    202 
    203   // Time to wait for a DHCP lease. Represented as field so that it
    204   // can be overriden in tests.
    205   unsigned int lease_acquisition_timeout_seconds_;
    206 
    207   // Called if a DHCP lease expires.
    208   base::CancelableClosure lease_expiration_callback_;
    209 
    210   // The minimum MTU value this configuration will respect.
    211   int minimum_mtu_;
    212 
    213   // Root file path, used for testing.
    214   base::FilePath root_;
    215 
    216   base::WeakPtrFactory<DHCPConfig> weak_ptr_factory_;
    217   EventDispatcher* dispatcher_;
    218   ProcessManager* process_manager_;
    219   Metrics* metrics_;
    220 
    221   DISALLOW_COPY_AND_ASSIGN(DHCPConfig);
    222 };
    223 
    224 }  // namespace shill
    225 
    226 #endif  // SHILL_DHCP_DHCP_CONFIG_H_
    227