blob: 3809f7e08df3dbaa4623f164707047157dbb3c0a [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>
Garrick Evans49879532018-12-03 13:15:36 +090010#include <set>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070011#include <string>
Garrick Evansc7fea0a2020-02-04 10:46:42 +090012#include <vector>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070013
14#include <base/macros.h>
15#include <base/memory/weak_ptr.h>
16#include <shill/dbus-proxies.h>
17
Garrick Evans3388a032020-03-24 11:25:55 +090018namespace patchpanel {
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070019
Jie Jiang850a4712020-04-08 21:06:36 +090020// Listens for shill signals over dbus in order to:
21// - Figure out which network interface (if any) is being used as the default
22// service.
23// - Invoke callbacks when the IPConfigs of a device has changed.
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070024class ShillClient {
25 public:
Jie Jiang850a4712020-04-08 21:06:36 +090026 // IPConfig for a device. If the device does not have a valid ipv4/ipv6
27 // config, the corresponding fields will be empty or 0.
28 // TODO(jiejiang): add the following fields into this struct:
29 // - IPv4 search domains
30 // - IPv6 search domains
31 // - MTU (one only per network)
32 struct IPConfig {
33 int ipv4_prefix_length;
34 std::string ipv4_address;
35 std::string ipv4_gateway;
36 std::vector<std::string> ipv4_dns_addresses;
37
38 int ipv6_prefix_length;
39 // Note due to the limitation of shill, we will only get one IPv6 address
40 // from it. This address should be the privacy address for device with type
41 // of ethernet or wifi.
42 std::string ipv6_address;
43 std::string ipv6_gateway;
44 std::vector<std::string> ipv6_dns_addresses;
45 };
46
Jie Jiang01c1a2e2020-04-08 20:58:30 +090047 // Represents the properties of an object of org.chromium.flimflam.Device.
48 // Only contains the properties we care about.
49 // TODO(jiejiang): add the following fields into this struct:
50 // - the DBus path of the Service associated to this Device if any
51 // - the connection state of the Service, if possible by translating back to
52 // the enum shill::Service::ConnectState
53 struct Device {
Jie Jiang48c99ce2020-06-08 15:18:23 +090054 // A subset of shill::Technology::Type.
55 enum class Type {
56 kUnknown,
57 kCellular,
58 kEthernet,
59 kEthernetEap,
60 kGuestInterface,
61 kLoopback,
62 kPPP,
63 kPPPoE,
64 kTunnel,
65 kVPN,
66 kWifi,
67 };
68
69 Type type;
Jie Jiang01c1a2e2020-04-08 20:58:30 +090070 std::string ifname;
71 IPConfig ipconfig;
72 };
73
Garrick Evans1b1f67c2020-02-04 16:21:25 +090074 using DefaultInterfaceChangeHandler = base::Callback<void(
75 const std::string& new_ifname, const std::string& prev_ifname)>;
Garrick Evans139708f2020-02-06 14:38:59 +090076 using DevicesChangeHandler =
77 base::Callback<void(const std::set<std::string>& added,
78 const std::set<std::string>& removed)>;
Jie Jiang850a4712020-04-08 21:06:36 +090079 using IPConfigsChangeHandler =
80 base::Callback<void(const std::string& device, const IPConfig& ipconfig)>;
Garrick Evans1b1f67c2020-02-04 16:21:25 +090081
Garrick Evans08843932019-09-17 14:41:08 +090082 explicit ShillClient(const scoped_refptr<dbus::Bus>& bus);
Ben Chan4f386502019-09-20 16:17:59 -070083 virtual ~ShillClient() = default;
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070084
85 void RegisterDefaultInterfaceChangedHandler(
Garrick Evans139708f2020-02-06 14:38:59 +090086 const DefaultInterfaceChangeHandler& handler);
Garrick Evans49879532018-12-03 13:15:36 +090087
Garrick Evans139708f2020-02-06 14:38:59 +090088 void RegisterDevicesChangedHandler(const DevicesChangeHandler& handler);
Garrick Evans49879532018-12-03 13:15:36 +090089
Jie Jiang850a4712020-04-08 21:06:36 +090090 void RegisterIPConfigsChangedHandler(const IPConfigsChangeHandler& handler);
91
Jie Jiang84c76a12020-04-17 16:45:20 +090092 void ScanDevices();
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070093
Jie Jiang01c1a2e2020-04-08 20:58:30 +090094 // Fetches device properties via dbus. Returns false if an error occurs. Notes
95 // that this method will block the current thread.
96 virtual bool GetDeviceProperties(const std::string& device, Device* output);
97
Garrick Evansbbdf4b42020-03-05 12:59:06 +090098 // Returns the cached interface name; does not initiate a property fetch.
99 virtual const std::string& default_interface() const;
Hugo Benichicc6850f2020-01-17 13:26:06 +0900100 // Returns interface names of all known shill Devices.
101 const std::set<std::string> get_devices() const;
102 // Returns true if |ifname| is a known shill Device.
103 bool has_device(const std::string& ifname) const;
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900104
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700105 protected:
106 void OnManagerPropertyChangeRegistration(const std::string& interface,
107 const std::string& signal_name,
108 bool success);
109 void OnManagerPropertyChange(const std::string& property_name,
110 const brillo::Any& property_value);
111
Jie Jiang850a4712020-04-08 21:06:36 +0900112 void OnDevicePropertyChangeRegistration(const std::string& interface,
113 const std::string& signal_name,
114 bool success);
115 void OnDevicePropertyChange(const std::string& device,
116 const std::string& property_name,
117 const brillo::Any& property_value);
118
Hugo Benichiddee2812019-05-10 16:03:43 +0900119 // Returns the name of the default interface for the system, or an empty
120 // string when the system has no default interface.
121 virtual std::string GetDefaultInterface();
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700122
Hugo Benichiddee2812019-05-10 16:03:43 +0900123 private:
Garrick Evans139708f2020-02-06 14:38:59 +0900124 void UpdateDevices(const brillo::Any& property_value);
125
Hugo Benichiddee2812019-05-10 16:03:43 +0900126 // Sets the internal variable tracking the system default interface and calls
127 // the default interface handler if the default interface changed. When the
128 // default interface is lost and a fallback exists, the fallback is used
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900129 // instead. Returns the previous default interface.
130 std::string SetDefaultInterface(std::string new_default);
Hugo Benichiddee2812019-05-10 16:03:43 +0900131
Jie Jiang850a4712020-04-08 21:06:36 +0900132 // Parses the |property_value| as the IPConfigs property of |device|, which
133 // should be a list of object paths of IPConfigs.
134 IPConfig ParseIPConfigsProperty(const std::string& device,
135 const brillo::Any& property_value);
136
Hugo Benichiddee2812019-05-10 16:03:43 +0900137 // Tracks the name of the system default interface chosen by shill.
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700138 std::string default_interface_;
Hugo Benichiddee2812019-05-10 16:03:43 +0900139 // Another network interface on the system to use as a possible fallback if
140 // no system default interface exists.
141 std::string fallback_default_interface_;
142 // Tracks all network interfaces managed by shill.
143 std::set<std::string> devices_;
Jie Jiang850a4712020-04-08 21:06:36 +0900144 // Stores the map from interface to its object path in shill for all the
145 // devices we have seen. Unlike |devices_|, entries in this map will never
146 // be removed during the lifetime of this class. We maintain this map mainly
147 // for keeping track of the device object proxies we have created, to avoid
148 // registering the handler on the same object twice.
149 std::map<std::string, dbus::ObjectPath> known_device_paths_;
150
Hugo Benichiddee2812019-05-10 16:03:43 +0900151 // Called when the interface used as the default interface changes.
Garrick Evans139708f2020-02-06 14:38:59 +0900152 std::vector<DefaultInterfaceChangeHandler> default_interface_handlers_;
Hugo Benichiddee2812019-05-10 16:03:43 +0900153 // Called when the list of network interfaces managed by shill changes.
Garrick Evans139708f2020-02-06 14:38:59 +0900154 std::vector<DevicesChangeHandler> device_handlers_;
Jie Jiang850a4712020-04-08 21:06:36 +0900155 // Called when the IPConfigs of any device changes.
156 std::vector<IPConfigsChangeHandler> ipconfigs_handlers_;
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700157
158 scoped_refptr<dbus::Bus> bus_;
159 std::unique_ptr<org::chromium::flimflam::ManagerProxy> manager_proxy_;
160
161 base::WeakPtrFactory<ShillClient> weak_factory_{this};
162
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700163 DISALLOW_COPY_AND_ASSIGN(ShillClient);
164};
165
Garrick Evans3388a032020-03-24 11:25:55 +0900166} // namespace patchpanel
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700167
Garrick Evans3388a032020-03-24 11:25:55 +0900168#endif // PATCHPANEL_SHILL_CLIENT_H_