blob: 39747021c4f638fc3e215f1b6c40f37147f4dbb6 [file] [log] [blame]
Garrick Evans5d55f5e2019-07-17 15:28:10 +09001// Copyright 2019 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#include "patchpanel/arc_service.h"
Garrick Evans5d55f5e2019-07-17 15:28:10 +09006
Garrick Evans54861622019-07-19 09:05:09 +09007#include <linux/rtnetlink.h>
8#include <net/if.h>
Garrick Evans71e4a862020-05-18 12:22:23 +09009#include <sys/utsname.h>
Garrick Evans54861622019-07-19 09:05:09 +090010
Garrick Evans5d55f5e2019-07-17 15:28:10 +090011#include <utility>
12
Garrick Evans54861622019-07-19 09:05:09 +090013#include <base/bind.h>
Garrick Evans5d55f5e2019-07-17 15:28:10 +090014#include <base/files/file_path.h>
15#include <base/files/file_util.h>
16#include <base/logging.h>
17#include <base/strings/string_number_conversions.h>
Qijiang Fan2d7aeb42020-05-19 02:06:39 +090018#include <base/system/sys_info.h>
Garrick Evans1f5a3612019-11-08 12:59:03 +090019#include <brillo/key_value_store.h>
Garrick Evansb4eb3892019-11-13 12:07:07 +090020#include <chromeos/constants/vm_tools.h>
Garrick Evans54861622019-07-19 09:05:09 +090021
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +090022#include "patchpanel/adb_proxy.h"
Garrick Evans3388a032020-03-24 11:25:55 +090023#include "patchpanel/mac_address_generator.h"
24#include "patchpanel/manager.h"
25#include "patchpanel/minijailed_process_runner.h"
26#include "patchpanel/net_util.h"
27#include "patchpanel/scoped_ns.h"
Garrick Evans5d55f5e2019-07-17 15:28:10 +090028
Garrick Evans3388a032020-03-24 11:25:55 +090029namespace patchpanel {
Garrick Evans5d55f5e2019-07-17 15:28:10 +090030namespace {
Hugo Benichi0781d402021-02-22 13:43:11 +090031// UID of Android root, relative to the host pid namespace.
Hugo Benichi6c0233e2020-10-06 22:37:57 +090032const int32_t kAndroidRootUid = 655360;
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +090033constexpr uint32_t kInvalidId = 0;
Hugo Benichi33860d72020-07-09 16:34:01 +090034constexpr char kArcNetnsName[] = "arc_netns";
Garrick Evanse94b6de2020-02-20 09:19:13 +090035constexpr char kArcIfname[] = "arc0";
Hugo Benichi84d96c42021-02-26 14:20:13 +090036
37bool IsAdbAllowed(ShillClient::Device::Type type) {
38 static const std::set<ShillClient::Device::Type> adb_allowed_types{
39 ShillClient::Device::Type::kEthernet,
40 ShillClient::Device::Type::kEthernetEap,
41 ShillClient::Device::Type::kWifi,
42 };
43 return adb_allowed_types.find(type) != adb_allowed_types.end();
44}
45
Garrick Evans71e4a862020-05-18 12:22:23 +090046bool KernelVersion(int* major, int* minor) {
47 struct utsname u;
48 if (uname(&u) != 0) {
49 PLOG(ERROR) << "uname failed";
50 *major = *minor = 0;
51 return false;
52 }
53 int unused;
54 if (sscanf(u.release, "%d.%d.%d", major, minor, &unused) != 3) {
55 LOG(ERROR) << "unexpected release string: " << u.release;
56 *major = *minor = 0;
57 return false;
58 }
59 return true;
60}
61
Hugo Benichi0781d402021-02-22 13:43:11 +090062// Makes Android root the owner of /sys/class/ + |path|. |pid| is the ARC
63// container pid.
64void SetSysfsOwnerToAndroidRoot(uint32_t pid, const std::string& path) {
Jie Jiangf6799312021-05-14 16:27:03 +090065 auto ns = ScopedNS::EnterMountNS(pid);
66 if (!ns) {
Hugo Benichi0781d402021-02-22 13:43:11 +090067 LOG(ERROR) << "Cannot enter mnt namespace for pid " << pid;
68 return;
69 }
70
71 const std::string sysfs_path = "/sys/class/" + path;
72 if (chown(sysfs_path.c_str(), kAndroidRootUid, kAndroidRootUid) == -1)
73 PLOG(ERROR) << "Failed to change ownership of " + sysfs_path;
74}
75
76void OneTimeContainerSetup(const Datapath& datapath, uint32_t pid) {
Garrick Evansa34b5862019-11-20 09:34:01 +090077 static bool done = false;
78 if (done)
79 return;
80
Garrick Evans6d227b92019-12-03 16:11:29 +090081 auto& runner = datapath.runner();
82
83 // Load networking modules needed by Android that are not compiled in the
84 // kernel. Android does not allow auto-loading of kernel modules.
Garrick Evansc53b9702020-05-13 13:20:09 +090085 // Expected for all kernels.
Garrick Evans8e8e3472020-01-23 14:03:50 +090086 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +090087 // The netfilter modules needed by netd for iptables commands.
88 "ip6table_filter",
89 "ip6t_ipv6header",
90 "ip6t_REJECT",
Garrick Evansa34b5862019-11-20 09:34:01 +090091 // The ipsec modules for AH and ESP encryption for ipv6.
92 "ah6",
93 "esp6",
94 }) != 0) {
95 LOG(ERROR) << "One or more required kernel modules failed to load."
96 << " Some Android functionality may be broken.";
97 }
Garrick Evansc53b9702020-05-13 13:20:09 +090098 // The xfrm modules needed for Android's ipsec APIs on kernels < 5.4.
Garrick Evans71e4a862020-05-18 12:22:23 +090099 int major, minor;
100 if (KernelVersion(&major, &minor) &&
101 (major < 5 || (major == 5 && minor < 4)) &&
102 runner.modprobe_all({
103 "xfrm4_mode_transport",
104 "xfrm4_mode_tunnel",
105 "xfrm6_mode_transport",
106 "xfrm6_mode_tunnel",
107 }) != 0) {
Garrick Evansc53b9702020-05-13 13:20:09 +0900108 LOG(ERROR) << "One or more required kernel modules failed to load."
109 << " Some Android functionality may be broken.";
110 }
111
Garrick Evansa34b5862019-11-20 09:34:01 +0900112 // Optional modules.
Garrick Evans8e8e3472020-01-23 14:03:50 +0900113 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +0900114 // This module is not available in kernels < 3.18
115 "nf_reject_ipv6",
116 // These modules are needed for supporting Chrome traffic on Android
117 // VPN which uses Android's NAT feature. Android NAT sets up
118 // iptables
119 // rules that use these conntrack modules for FTP/TFTP.
120 "nf_nat_ftp",
121 "nf_nat_tftp",
Hugo Benichia0cde9e2019-12-16 11:57:20 +0900122 // The tun module is needed by the Android 464xlat clatd process.
123 "tun",
Garrick Evansa34b5862019-11-20 09:34:01 +0900124 }) != 0) {
125 LOG(WARNING) << "One or more optional kernel modules failed to load.";
126 }
127
Garrick Evans6d227b92019-12-03 16:11:29 +0900128 // This is only needed for CTS (b/27932574).
Hugo Benichi0781d402021-02-22 13:43:11 +0900129 SetSysfsOwnerToAndroidRoot(pid, "xt_idletimer");
Garrick Evans6d227b92019-12-03 16:11:29 +0900130
Garrick Evansa34b5862019-11-20 09:34:01 +0900131 done = true;
132}
133
Hugo Benichif0f10c72020-07-09 10:42:45 +0900134// Returns the ARC management device used for VPN forwarding, ADB-over-TCP.
135std::unique_ptr<Device> MakeArcDevice(AddressManager* addr_mgr,
136 GuestMessage::GuestType guest) {
137 auto ipv4_subnet = addr_mgr->AllocateIPv4Subnet(AddressManager::Guest::ARC);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900138 if (!ipv4_subnet) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900139 LOG(ERROR) << "Subnet already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900140 return nullptr;
141 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900142
Garrick Evanse94b6de2020-02-20 09:19:13 +0900143 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
144 if (!host_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900145 LOG(ERROR) << "Bridge address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900146 return nullptr;
147 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900148
Garrick Evanse94b6de2020-02-20 09:19:13 +0900149 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
150 if (!guest_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900151 LOG(ERROR) << "ARC address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900152 return nullptr;
153 }
154
Hugo Benichif0f10c72020-07-09 10:42:45 +0900155 int subnet_index = (guest == GuestMessage::ARC_VM) ? 1 : kAnySubnetIndex;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900156
Hugo Benichif0f10c72020-07-09 10:42:45 +0900157 auto config = std::make_unique<Device::Config>(
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900158 addr_mgr->GenerateMacAddress(subnet_index), std::move(ipv4_subnet),
159 std::move(host_ipv4_addr), std::move(guest_ipv4_addr));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900160
Hugo Benichif0f10c72020-07-09 10:42:45 +0900161 return std::make_unique<Device>(kArcIfname, kArcBridge, kArcIfname,
Hugo Benichi6f118a32021-03-01 12:28:14 +0900162 std::move(config));
Hugo Benichif0f10c72020-07-09 10:42:45 +0900163}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900164} // namespace
165
Garrick Evans69b85872020-02-04 11:40:26 +0900166ArcService::ArcService(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900167 Datapath* datapath,
168 AddressManager* addr_mgr,
Garrick Evans209a80a2020-11-30 14:42:40 +0900169 GuestMessage::GuestType guest,
170 Device::ChangeEventHandler device_changed_handler)
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900171 : shill_client_(shill_client),
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900172 datapath_(datapath),
173 addr_mgr_(addr_mgr),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900174 guest_(guest),
Garrick Evans209a80a2020-11-30 14:42:40 +0900175 device_changed_handler_(device_changed_handler),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900176 id_(kInvalidId) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900177 arc_device_ = MakeArcDevice(addr_mgr, guest_);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900178 AllocateAddressConfigs();
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900179 shill_client_->RegisterDevicesChangedHandler(
180 base::Bind(&ArcService::OnDevicesChanged, weak_factory_.GetWeakPtr()));
Jie Jiang84c76a12020-04-17 16:45:20 +0900181 shill_client_->ScanDevices();
Garrick Evansf29f5a32019-12-06 11:34:25 +0900182}
183
184ArcService::~ArcService() {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900185 if (IsStarted()) {
186 Stop(id_);
Garrick Evans664a82f2019-12-17 12:18:05 +0900187 }
Garrick Evans54861622019-07-19 09:05:09 +0900188}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900189
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900190bool ArcService::IsStarted() const {
191 return id_ != kInvalidId;
192}
193
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900194void ArcService::AllocateAddressConfigs() {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900195 // The first usable subnet is the "other" ARC device subnet.
Garrick Evansc7071122020-04-17 12:31:57 +0900196 // As a temporary workaround, for ARCVM, allocate fixed MAC addresses.
197 uint8_t mac_addr_index = 2;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900198 // Allocate 2 subnets each for Ethernet and WiFi and 1 for LTE WAN interfaces.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900199 for (const auto type :
200 {ShillClient::Device::Type::kEthernet,
201 ShillClient::Device::Type::kEthernet, ShillClient::Device::Type::kWifi,
202 ShillClient::Device::Type::kWifi,
203 ShillClient::Device::Type::kCellular}) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900204 auto ipv4_subnet =
205 addr_mgr_->AllocateIPv4Subnet(AddressManager::Guest::ARC_NET);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900206 if (!ipv4_subnet) {
207 LOG(ERROR) << "Subnet already in use or unavailable";
208 continue;
209 }
210 // For here out, use the same slices.
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900211 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
212 if (!host_ipv4_addr) {
213 LOG(ERROR) << "Bridge address already in use or unavailable";
214 continue;
215 }
216 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
217 if (!guest_ipv4_addr) {
218 LOG(ERROR) << "ARC address already in use or unavailable";
219 continue;
220 }
221
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900222 MacAddress mac_addr = (guest_ == GuestMessage::ARC_VM)
Garrick Evansc7071122020-04-17 12:31:57 +0900223 ? addr_mgr_->GenerateMacAddress(mac_addr_index++)
224 : addr_mgr_->GenerateMacAddress();
Hugo Benichi84d96c42021-02-26 14:20:13 +0900225 available_configs_[type].emplace_back(std::make_unique<Device::Config>(
Garrick Evansc7071122020-04-17 12:31:57 +0900226 mac_addr, std::move(ipv4_subnet), std::move(host_ipv4_addr),
227 std::move(guest_ipv4_addr)));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900228 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900229
Hugo Benichi84d96c42021-02-26 14:20:13 +0900230 all_configs_.push_back(&arc_device_->config());
231 // Iterate over |available_configs_| with a fixed explicit order and do not
232 // rely on the implicit ordering derived from key values.
233 for (const auto type :
234 {ShillClient::Device::Type::kEthernet, ShillClient::Device::Type::kWifi,
235 ShillClient::Device::Type::kCellular}) {
236 for (const auto& c : available_configs_[type]) {
237 all_configs_.push_back(c.get());
238 }
239 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900240}
241
242std::unique_ptr<Device::Config> ArcService::AcquireConfig(
Hugo Benichi84d96c42021-02-26 14:20:13 +0900243 ShillClient::Device::Type type) {
244 // Normalize shill Device types for different ethernet flavors.
245 if (type == ShillClient::Device::Type::kEthernetEap)
246 type = ShillClient::Device::Type::kEthernet;
247
248 auto it = available_configs_.find(type);
249 if (it == available_configs_.end()) {
250 LOG(ERROR) << "Unsupported shill Device type " << type;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900251 return nullptr;
252 }
253
Hugo Benichi84d96c42021-02-26 14:20:13 +0900254 if (it->second.empty()) {
255 LOG(ERROR)
256 << "Cannot make virtual device: No more addresses available for type "
257 << type;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900258 return nullptr;
259 }
Hugo Benichi84d96c42021-02-26 14:20:13 +0900260
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900261 std::unique_ptr<Device::Config> config;
Hugo Benichi84d96c42021-02-26 14:20:13 +0900262 config = std::move(it->second.front());
263 it->second.pop_front();
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900264 return config;
265}
266
Hugo Benichi84d96c42021-02-26 14:20:13 +0900267void ArcService::ReleaseConfig(ShillClient::Device::Type type,
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900268 std::unique_ptr<Device::Config> config) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900269 available_configs_[type].push_front(std::move(config));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900270}
271
Garrick Evans015b0d62020-02-07 09:06:38 +0900272bool ArcService::Start(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900273 if (IsStarted()) {
274 LOG(WARNING) << "Already running - did something crash?"
275 << " Stopping and restarting...";
276 Stop(id_);
Garrick Evansa51d0a12019-11-28 13:51:23 +0900277 }
278
Hugo Benichif0f10c72020-07-09 10:42:45 +0900279 std::string arc_device_ifname;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900280 if (guest_ == GuestMessage::ARC_VM) {
Hugo Benichi8e448422020-07-07 10:49:00 +0900281 // Allocate TAP devices for all configs.
282 for (auto* config : all_configs_) {
283 auto mac = config->mac_addr();
284 auto tap = datapath_->AddTAP("" /* auto-generate name */, &mac,
285 nullptr /* no ipv4 subnet */,
286 vm_tools::kCrosVmUser);
287 if (tap.empty()) {
288 LOG(ERROR) << "Failed to create TAP device";
289 continue;
290 }
291
292 config->set_tap_ifname(tap);
293 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900294 arc_device_ifname = arc_device_->config().tap_ifname();
Garrick Evans2961c7c2020-04-03 11:34:40 +0900295 } else {
Hugo Benichi0781d402021-02-22 13:43:11 +0900296 OneTimeContainerSetup(*datapath_, id);
Hugo Benichi33860d72020-07-09 16:34:01 +0900297 if (!datapath_->NetnsAttachName(kArcNetnsName, id)) {
298 LOG(ERROR) << "Failed to attach name " << kArcNetnsName << " to pid "
299 << id;
300 return false;
301 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900302 arc_device_ifname = ArcVethHostName(arc_device_->guest_ifname());
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900303 if (!datapath_->ConnectVethPair(id, kArcNetnsName, arc_device_ifname,
304 arc_device_->guest_ifname(),
305 arc_device_->config().mac_addr(),
306 arc_device_->config().guest_ipv4_addr(), 30,
Hugo Benichi6f118a32021-03-01 12:28:14 +0900307 false /*remote_multicast_flag*/)) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900308 LOG(ERROR) << "Cannot create virtual link for device "
309 << arc_device_->phys_ifname();
310 return false;
311 }
Hugo Benichi40fbf0b2021-01-20 19:44:15 +0900312 // Allow netd to write to /sys/class/net/arc0/mtu (b/175571457).
Hugo Benichi0781d402021-02-22 13:43:11 +0900313 SetSysfsOwnerToAndroidRoot(id,
314 "net/" + arc_device_->guest_ifname() + "/mtu");
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900315 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900316 id_ = id;
317
318 // Create the bridge for the management device arc0.
319 // Per crbug/1008686 this device cannot be deleted and then re-added.
320 // So instead of removing the bridge when the service stops, bring down the
321 // device instead and re-up it on restart.
322 if (!datapath_->AddBridge(kArcBridge, arc_device_->config().host_ipv4_addr(),
323 30) &&
324 !datapath_->MaskInterfaceFlags(kArcBridge, IFF_UP)) {
325 LOG(ERROR) << "Failed to bring up arc bridge " << kArcBridge;
326 return false;
327 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900328
329 if (!datapath_->AddToBridge(kArcBridge, arc_device_ifname)) {
330 LOG(ERROR) << "Failed to bridge arc device " << arc_device_ifname << " to "
331 << kArcBridge;
332 return false;
333 }
Hugo Benichi33860d72020-07-09 16:34:01 +0900334 LOG(INFO) << "Started ARC management device " << *arc_device_.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900335
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900336 // Start already known Shill <-> ARC mapped devices.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900337 for (const auto& [ifname, type] : shill_devices_)
338 AddDevice(ifname, type);
Garrick Evanscb791e72019-11-11 15:44:34 +0900339
Damien Dejean61eccae2021-05-21 07:11:53 +0000340 // Enable conntrack helpers (b/172214190).
341 if (!datapath_->SetConntrackHelpers(true)) {
342 LOG(ERROR) << "Failed to enable conntrack helpers";
343 return false;
344 }
345
Garrick Evansf29f5a32019-12-06 11:34:25 +0900346 return true;
Garrick Evanscb791e72019-11-11 15:44:34 +0900347}
348
Garrick Evans015b0d62020-02-07 09:06:38 +0900349void ArcService::Stop(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900350 if (!IsStarted()) {
351 LOG(ERROR) << "ArcService was not running";
352 return;
353 }
354
355 // After the ARC container has stopped, the pid is not known anymore.
356 if (guest_ == GuestMessage::ARC_VM && id_ != id) {
357 LOG(ERROR) << "Mismatched ARCVM CIDs " << id_ << " != " << id;
358 return;
359 }
360
Damien Dejean61eccae2021-05-21 07:11:53 +0000361 if (!datapath_->SetConntrackHelpers(false))
362 LOG(ERROR) << "Failed to disable conntrack helpers";
363
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900364 // Stop Shill <-> ARC mapped devices.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900365 for (const auto& [ifname, type] : shill_devices_)
366 RemoveDevice(ifname, type);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900367
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900368 // Per crbug/1008686 this device cannot be deleted and then re-added.
369 // So instead of removing the bridge, bring it down and mark it. This will
370 // allow us to detect if the device is re-added in case of a crash restart
371 // and do the right thing.
372 if (!datapath_->MaskInterfaceFlags(kArcBridge, IFF_DEBUG, IFF_UP))
373 LOG(ERROR) << "Failed to bring down arc bridge "
374 << "- it may not restart correctly";
375
Hugo Benichi33860d72020-07-09 16:34:01 +0900376 if (guest_ == GuestMessage::ARC) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900377 datapath_->RemoveInterface(ArcVethHostName(arc_device_->phys_ifname()));
Hugo Benichi33860d72020-07-09 16:34:01 +0900378 if (!datapath_->NetnsDeleteName(kArcNetnsName))
379 LOG(WARNING) << "Failed to delete netns name " << kArcNetnsName;
Hugo Benichif0f10c72020-07-09 10:42:45 +0900380 }
381
382 // Destroy allocated TAP devices if any, including the ARC management device.
383 for (auto* config : all_configs_) {
384 if (config->tap_ifname().empty())
385 continue;
386 datapath_->RemoveInterface(config->tap_ifname());
387 config->set_tap_ifname("");
Hugo Benichi33860d72020-07-09 16:34:01 +0900388 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900389
Hugo Benichi33860d72020-07-09 16:34:01 +0900390 LOG(INFO) << "Stopped ARC management device " << *arc_device_.get();
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900391 id_ = kInvalidId;
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900392}
393
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900394void ArcService::OnDevicesChanged(const std::set<std::string>& added,
395 const std::set<std::string>& removed) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900396 for (const std::string& ifname : removed) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900397 RemoveDevice(ifname, shill_devices_[ifname]);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900398 shill_devices_.erase(ifname);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900399 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900400
Hugo Benichif0f10c72020-07-09 10:42:45 +0900401 for (const std::string& ifname : added) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900402 ShillClient::Device shill_device;
403 if (!shill_client_->GetDeviceProperties(ifname, &shill_device)) {
404 LOG(ERROR) << "Could not read shill Device properties for " << ifname;
405 continue;
406 }
407 shill_devices_[ifname] = shill_device.type;
408 AddDevice(ifname, shill_device.type);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900409 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900410}
411
Hugo Benichi84d96c42021-02-26 14:20:13 +0900412void ArcService::AddDevice(const std::string& ifname,
413 ShillClient::Device::Type type) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900414 if (!IsStarted())
415 return;
416
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900417 if (ifname.empty())
418 return;
419
420 if (devices_.find(ifname) != devices_.end()) {
421 LOG(DFATAL) << "Attemping to add already tracked device: " << ifname;
422 return;
423 }
424
Hugo Benichi84d96c42021-02-26 14:20:13 +0900425 auto config = AcquireConfig(type);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900426 if (!config) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900427 LOG(ERROR) << "Cannot acquire a Config for " << ifname;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900428 return;
429 }
430
Garrick Evans8a067562020-05-11 12:47:30 +0900431 auto device = std::make_unique<Device>(ifname, ArcBridgeName(ifname), ifname,
Hugo Benichi6f118a32021-03-01 12:28:14 +0900432 std::move(config));
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900433 LOG(INFO) << "Starting device " << *device;
Garrick Evans54861622019-07-19 09:05:09 +0900434
435 // Create the bridge.
Hugo Benichif0f10c72020-07-09 10:42:45 +0900436 if (!datapath_->AddBridge(device->host_ifname(),
437 device->config().host_ipv4_addr(), 30)) {
438 LOG(ERROR) << "Failed to setup bridge " << device->host_ifname();
Garrick Evanse94b6de2020-02-20 09:19:13 +0900439 return;
Garrick Evans54861622019-07-19 09:05:09 +0900440 }
441
Hugo Benichi8d622b52020-08-13 15:24:12 +0900442 datapath_->StartRoutingDevice(device->phys_ifname(), device->host_ifname(),
443 device->config().guest_ipv4_addr(),
Hugo Benichi93306e52020-12-04 16:08:00 +0900444 TrafficSource::ARC, false /*route_on_vpn*/);
Garrick Evans2c263102019-07-26 16:07:18 +0900445
Hugo Benichicf904022020-07-07 09:21:58 +0900446 std::string virtual_device_ifname;
447 if (guest_ == GuestMessage::ARC_VM) {
448 virtual_device_ifname = device->config().tap_ifname();
449 if (virtual_device_ifname.empty()) {
450 LOG(ERROR) << "No TAP device for " << *device;
451 return;
452 }
453 } else {
454 virtual_device_ifname = ArcVethHostName(device->guest_ifname());
455 if (!datapath_->ConnectVethPair(
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900456 id_, kArcNetnsName, virtual_device_ifname, device->guest_ifname(),
Hugo Benichicf904022020-07-07 09:21:58 +0900457 device->config().mac_addr(), device->config().guest_ipv4_addr(), 30,
Hugo Benichi6f118a32021-03-01 12:28:14 +0900458 IsMulticastInterface(device->phys_ifname()))) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900459 LOG(ERROR) << "Cannot create veth link for device " << *device;
Hugo Benichicf904022020-07-07 09:21:58 +0900460 return;
461 }
Hugo Benichi6c0233e2020-10-06 22:37:57 +0900462 // Allow netd to write to /sys/class/net/<guest_ifname>/mtu (b/169936104).
Hugo Benichi0781d402021-02-22 13:43:11 +0900463 SetSysfsOwnerToAndroidRoot(id_, "net/" + device->guest_ifname() + "/mtu");
Hugo Benichicf904022020-07-07 09:21:58 +0900464 }
465
466 if (!datapath_->AddToBridge(device->host_ifname(), virtual_device_ifname)) {
467 if (guest_ == GuestMessage::ARC) {
468 datapath_->RemoveInterface(virtual_device_ifname);
469 }
470 LOG(ERROR) << "Failed to bridge interface " << virtual_device_ifname;
Hugo Benichi4833fda2020-07-06 14:56:56 +0900471 return;
472 }
473
Hugo Benichi6f118a32021-03-01 12:28:14 +0900474 if (IsAdbAllowed(type) && !datapath_->AddAdbPortAccessRule(ifname)) {
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900475 LOG(ERROR) << "Failed to add ADB port access rule";
476 }
477
Garrick Evans209a80a2020-11-30 14:42:40 +0900478 device_changed_handler_.Run(*device, Device::ChangeEvent::ADDED, guest_);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900479 devices_.emplace(ifname, std::move(device));
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900480}
481
Hugo Benichi84d96c42021-02-26 14:20:13 +0900482void ArcService::RemoveDevice(const std::string& ifname,
483 ShillClient::Device::Type type) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900484 if (!IsStarted())
485 return;
486
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900487 const auto it = devices_.find(ifname);
488 if (it == devices_.end()) {
489 LOG(WARNING) << "Unknown device: " << ifname;
Garrick Evanscb791e72019-11-11 15:44:34 +0900490 return;
491 }
492
Hugo Benichif0f10c72020-07-09 10:42:45 +0900493 const auto* device = it->second.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900494 LOG(INFO) << "Removing device " << *device;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900495
Garrick Evans209a80a2020-11-30 14:42:40 +0900496 device_changed_handler_.Run(*device, Device::ChangeEvent::REMOVED, guest_);
497
Hugo Benichif0f10c72020-07-09 10:42:45 +0900498 // ARCVM TAP devices are removed in VmImpl::Stop() when the service stops
Hugo Benichi4833fda2020-07-06 14:56:56 +0900499 if (guest_ == GuestMessage::ARC)
500 datapath_->RemoveInterface(ArcVethHostName(device->phys_ifname()));
Garrick Evans54861622019-07-19 09:05:09 +0900501
Hugo Benichi8d622b52020-08-13 15:24:12 +0900502 datapath_->StopRoutingDevice(device->phys_ifname(), device->host_ifname(),
503 device->config().guest_ipv4_addr(),
Hugo Benichi93306e52020-12-04 16:08:00 +0900504 TrafficSource::ARC, false /*route_on_vpn*/);
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900505 datapath_->RemoveBridge(device->host_ifname());
Hugo Benichi6f118a32021-03-01 12:28:14 +0900506 if (IsAdbAllowed(type))
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900507 datapath_->DeleteAdbPortAccessRule(ifname);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900508
Hugo Benichi84d96c42021-02-26 14:20:13 +0900509 // Once the physical Device is gone it may not be possible to retrieve
510 // the device type from Shill DBus interface by interface name.
511 ReleaseConfig(type, it->second->release_config());
Hugo Benichif0f10c72020-07-09 10:42:45 +0900512 devices_.erase(it);
Garrick Evanscb791e72019-11-11 15:44:34 +0900513}
514
Garrick Evans38b25a42020-04-06 15:17:42 +0900515std::vector<const Device::Config*> ArcService::GetDeviceConfigs() const {
Hugo Benichi8e448422020-07-07 10:49:00 +0900516 std::vector<const Device::Config*> configs;
517 for (auto* c : all_configs_)
518 configs.emplace_back(c);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900519
Hugo Benichi8e448422020-07-07 10:49:00 +0900520 return configs;
Garrick Evanse94b6de2020-02-20 09:19:13 +0900521}
Garrick Evans02e6e872020-11-30 11:53:13 +0900522
523void ArcService::ScanDevices(
524 base::RepeatingCallback<void(const Device&)> callback) const {
525 for (const auto& [_, d] : devices_)
526 callback.Run(*d.get());
527}
528
Garrick Evans3388a032020-03-24 11:25:55 +0900529} // namespace patchpanel