blob: ba6d86c9ff0672c269e5409ecd8e514e707fc630 [file] [log] [blame]
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07001// Copyright 2016 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Garrick Evans3388a032020-03-24 11:25:55 +09005#ifndef PATCHPANEL_SHILL_CLIENT_H_
6#define PATCHPANEL_SHILL_CLIENT_H_
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07007
Jie Jiang850a4712020-04-08 21:06:36 +09008#include <map>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07009#include <memory>
Hugo Benichi78148a02020-10-30 18:37:00 +090010#include <ostream>
Garrick Evans49879532018-12-03 13:15:36 +090011#include <set>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070012#include <string>
Garrick Evansc7fea0a2020-02-04 10:46:42 +090013#include <vector>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070014
15#include <base/macros.h>
16#include <base/memory/weak_ptr.h>
17#include <shill/dbus-proxies.h>
18
Garrick Evans3388a032020-03-24 11:25:55 +090019namespace patchpanel {
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070020
Jie Jiang850a4712020-04-08 21:06:36 +090021// Listens for shill signals over dbus in order to:
22// - Figure out which network interface (if any) is being used as the default
23// service.
24// - Invoke callbacks when the IPConfigs of a device has changed.
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070025class ShillClient {
26 public:
Jie Jiang850a4712020-04-08 21:06:36 +090027 // IPConfig for a device. If the device does not have a valid ipv4/ipv6
28 // config, the corresponding fields will be empty or 0.
29 // TODO(jiejiang): add the following fields into this struct:
30 // - IPv4 search domains
31 // - IPv6 search domains
32 // - MTU (one only per network)
33 struct IPConfig {
34 int ipv4_prefix_length;
35 std::string ipv4_address;
36 std::string ipv4_gateway;
37 std::vector<std::string> ipv4_dns_addresses;
38
39 int ipv6_prefix_length;
40 // Note due to the limitation of shill, we will only get one IPv6 address
41 // from it. This address should be the privacy address for device with type
42 // of ethernet or wifi.
43 std::string ipv6_address;
44 std::string ipv6_gateway;
45 std::vector<std::string> ipv6_dns_addresses;
46 };
47
Jie Jiang01c1a2e2020-04-08 20:58:30 +090048 // Represents the properties of an object of org.chromium.flimflam.Device.
49 // Only contains the properties we care about.
50 // TODO(jiejiang): add the following fields into this struct:
51 // - the DBus path of the Service associated to this Device if any
52 // - the connection state of the Service, if possible by translating back to
53 // the enum shill::Service::ConnectState
54 struct Device {
Jie Jiang48c99ce2020-06-08 15:18:23 +090055 // A subset of shill::Technology::Type.
56 enum class Type {
57 kUnknown,
58 kCellular,
59 kEthernet,
60 kEthernetEap,
61 kGuestInterface,
62 kLoopback,
63 kPPP,
64 kPPPoE,
65 kTunnel,
66 kVPN,
67 kWifi,
68 };
69
70 Type type;
Jie Jiang01c1a2e2020-04-08 20:58:30 +090071 std::string ifname;
Hugo Benichi78148a02020-10-30 18:37:00 +090072 std::string service_path;
Jie Jiang01c1a2e2020-04-08 20:58:30 +090073 IPConfig ipconfig;
74 };
75
Hugo Benichi78148a02020-10-30 18:37:00 +090076 using DefaultDeviceChangeHandler =
77 base::Callback<void(const Device& new_device, const Device& prev_device)>;
Garrick Evans139708f2020-02-06 14:38:59 +090078 using DevicesChangeHandler =
79 base::Callback<void(const std::set<std::string>& added,
80 const std::set<std::string>& removed)>;
Jie Jiang850a4712020-04-08 21:06:36 +090081 using IPConfigsChangeHandler =
82 base::Callback<void(const std::string& device, const IPConfig& ipconfig)>;
Garrick Evans1b1f67c2020-02-04 16:21:25 +090083
Garrick Evans08843932019-09-17 14:41:08 +090084 explicit ShillClient(const scoped_refptr<dbus::Bus>& bus);
Qijiang Fan6bc59e12020-11-11 02:51:06 +090085 ShillClient(const ShillClient&) = delete;
86 ShillClient& operator=(const ShillClient&) = delete;
87
Ben Chan4f386502019-09-20 16:17:59 -070088 virtual ~ShillClient() = default;
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070089
Hugo Benichi78148a02020-10-30 18:37:00 +090090 // Registers the provided handler for changes in shill default network
91 // services. The handler will be called once immediately at registration
92 // with the current default network as |new_device| and an empty Device as
93 // |prev_device|.
94 void RegisterDefaultDeviceChangedHandler(
95 const DefaultDeviceChangeHandler& handler);
Garrick Evans49879532018-12-03 13:15:36 +090096
Garrick Evans139708f2020-02-06 14:38:59 +090097 void RegisterDevicesChangedHandler(const DevicesChangeHandler& handler);
Garrick Evans49879532018-12-03 13:15:36 +090098
Jie Jiang850a4712020-04-08 21:06:36 +090099 void RegisterIPConfigsChangedHandler(const IPConfigsChangeHandler& handler);
100
Jie Jiang84c76a12020-04-17 16:45:20 +0900101 void ScanDevices();
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700102
Jie Jiang01c1a2e2020-04-08 20:58:30 +0900103 // Fetches device properties via dbus. Returns false if an error occurs. Notes
104 // that this method will block the current thread.
105 virtual bool GetDeviceProperties(const std::string& device, Device* output);
106
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900107 // Returns the cached interface name; does not initiate a property fetch.
108 virtual const std::string& default_interface() const;
Hugo Benichicc6850f2020-01-17 13:26:06 +0900109 // Returns interface names of all known shill Devices.
110 const std::set<std::string> get_devices() const;
111 // Returns true if |ifname| is a known shill Device.
112 bool has_device(const std::string& ifname) const;
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900113
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700114 protected:
115 void OnManagerPropertyChangeRegistration(const std::string& interface,
116 const std::string& signal_name,
117 bool success);
118 void OnManagerPropertyChange(const std::string& property_name,
119 const brillo::Any& property_value);
120
Jie Jiang850a4712020-04-08 21:06:36 +0900121 void OnDevicePropertyChangeRegistration(const std::string& interface,
122 const std::string& signal_name,
123 bool success);
124 void OnDevicePropertyChange(const std::string& device,
125 const std::string& property_name,
126 const brillo::Any& property_value);
127
Hugo Benichi78148a02020-10-30 18:37:00 +0900128 // Returns the default interface for the system, or an empty Device result
129 // when the system has no default interface.
130 virtual Device GetDefaultDevice();
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700131
Hugo Benichiddee2812019-05-10 16:03:43 +0900132 private:
Garrick Evans139708f2020-02-06 14:38:59 +0900133 void UpdateDevices(const brillo::Any& property_value);
134
Hugo Benichiddee2812019-05-10 16:03:43 +0900135 // Sets the internal variable tracking the system default interface and calls
Hugo Benichi78148a02020-10-30 18:37:00 +0900136 // the default interface handler if the default interface changed.
137 void SetDefaultDevice(const Device& new_default);
Hugo Benichiddee2812019-05-10 16:03:43 +0900138
Jie Jiang850a4712020-04-08 21:06:36 +0900139 // Parses the |property_value| as the IPConfigs property of |device|, which
140 // should be a list of object paths of IPConfigs.
141 IPConfig ParseIPConfigsProperty(const std::string& device,
142 const brillo::Any& property_value);
143
Hugo Benichi78148a02020-10-30 18:37:00 +0900144 // Tracks the system default logical network chosen by shill. This corresponds
145 // to the physical or virtual device associated with the default logical
146 // network service.
147 Device default_device_;
Hugo Benichiddee2812019-05-10 16:03:43 +0900148 // Tracks all network interfaces managed by shill.
149 std::set<std::string> devices_;
Jie Jiang850a4712020-04-08 21:06:36 +0900150 // Stores the map from interface to its object path in shill for all the
151 // devices we have seen. Unlike |devices_|, entries in this map will never
152 // be removed during the lifetime of this class. We maintain this map mainly
153 // for keeping track of the device object proxies we have created, to avoid
154 // registering the handler on the same object twice.
155 std::map<std::string, dbus::ObjectPath> known_device_paths_;
156
Hugo Benichiddee2812019-05-10 16:03:43 +0900157 // Called when the interface used as the default interface changes.
Hugo Benichi78148a02020-10-30 18:37:00 +0900158 std::vector<DefaultDeviceChangeHandler> default_device_handlers_;
Hugo Benichiddee2812019-05-10 16:03:43 +0900159 // Called when the list of network interfaces managed by shill changes.
Garrick Evans139708f2020-02-06 14:38:59 +0900160 std::vector<DevicesChangeHandler> device_handlers_;
Jie Jiang850a4712020-04-08 21:06:36 +0900161 // Called when the IPConfigs of any device changes.
162 std::vector<IPConfigsChangeHandler> ipconfigs_handlers_;
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700163
164 scoped_refptr<dbus::Bus> bus_;
165 std::unique_ptr<org::chromium::flimflam::ManagerProxy> manager_proxy_;
166
167 base::WeakPtrFactory<ShillClient> weak_factory_{this};
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700168};
169
Hugo Benichi78148a02020-10-30 18:37:00 +0900170std::ostream& operator<<(std::ostream& stream, const ShillClient::Device& dev);
171
Garrick Evans3388a032020-03-24 11:25:55 +0900172} // namespace patchpanel
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700173
Garrick Evans3388a032020-03-24 11:25:55 +0900174#endif // PATCHPANEL_SHILL_CLIENT_H_