blob: c2dbdaf5a4ae88c7fa89e82823b692a638bd5756 [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
Hugo Benichi69c989d2021-03-01 00:23:39 +090046// TODO(b/174538233): Remove once TrafficForwarder and Device::Option have been
47// removed.
Hugo Benichi84d96c42021-02-26 14:20:13 +090048bool IsIPv6NDProxyEnabled(ShillClient::Device::Type type) {
49 static const std::set<ShillClient::Device::Type> ndproxy_allowed_types{
50 ShillClient::Device::Type::kCellular,
51 ShillClient::Device::Type::kEthernet,
52 ShillClient::Device::Type::kEthernetEap,
53 ShillClient::Device::Type::kWifi,
54 };
55 return ndproxy_allowed_types.find(type) != ndproxy_allowed_types.end();
56}
Garrick Evans54861622019-07-19 09:05:09 +090057
Garrick Evans71e4a862020-05-18 12:22:23 +090058bool KernelVersion(int* major, int* minor) {
59 struct utsname u;
60 if (uname(&u) != 0) {
61 PLOG(ERROR) << "uname failed";
62 *major = *minor = 0;
63 return false;
64 }
65 int unused;
66 if (sscanf(u.release, "%d.%d.%d", major, minor, &unused) != 3) {
67 LOG(ERROR) << "unexpected release string: " << u.release;
68 *major = *minor = 0;
69 return false;
70 }
71 return true;
72}
73
Hugo Benichi0781d402021-02-22 13:43:11 +090074// Makes Android root the owner of /sys/class/ + |path|. |pid| is the ARC
75// container pid.
76void SetSysfsOwnerToAndroidRoot(uint32_t pid, const std::string& path) {
77 ScopedNS ns(pid, ScopedNS::Type::Mount);
78 if (!ns.IsValid()) {
79 LOG(ERROR) << "Cannot enter mnt namespace for pid " << pid;
80 return;
81 }
82
83 const std::string sysfs_path = "/sys/class/" + path;
84 if (chown(sysfs_path.c_str(), kAndroidRootUid, kAndroidRootUid) == -1)
85 PLOG(ERROR) << "Failed to change ownership of " + sysfs_path;
86}
87
88void OneTimeContainerSetup(const Datapath& datapath, uint32_t pid) {
Garrick Evansa34b5862019-11-20 09:34:01 +090089 static bool done = false;
90 if (done)
91 return;
92
Garrick Evans6d227b92019-12-03 16:11:29 +090093 auto& runner = datapath.runner();
94
95 // Load networking modules needed by Android that are not compiled in the
96 // kernel. Android does not allow auto-loading of kernel modules.
Garrick Evansc53b9702020-05-13 13:20:09 +090097 // Expected for all kernels.
Garrick Evans8e8e3472020-01-23 14:03:50 +090098 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +090099 // The netfilter modules needed by netd for iptables commands.
100 "ip6table_filter",
101 "ip6t_ipv6header",
102 "ip6t_REJECT",
Garrick Evansa34b5862019-11-20 09:34:01 +0900103 // The ipsec modules for AH and ESP encryption for ipv6.
104 "ah6",
105 "esp6",
106 }) != 0) {
107 LOG(ERROR) << "One or more required kernel modules failed to load."
108 << " Some Android functionality may be broken.";
109 }
Garrick Evansc53b9702020-05-13 13:20:09 +0900110 // The xfrm modules needed for Android's ipsec APIs on kernels < 5.4.
Garrick Evans71e4a862020-05-18 12:22:23 +0900111 int major, minor;
112 if (KernelVersion(&major, &minor) &&
113 (major < 5 || (major == 5 && minor < 4)) &&
114 runner.modprobe_all({
115 "xfrm4_mode_transport",
116 "xfrm4_mode_tunnel",
117 "xfrm6_mode_transport",
118 "xfrm6_mode_tunnel",
119 }) != 0) {
Garrick Evansc53b9702020-05-13 13:20:09 +0900120 LOG(ERROR) << "One or more required kernel modules failed to load."
121 << " Some Android functionality may be broken.";
122 }
123
Garrick Evansa34b5862019-11-20 09:34:01 +0900124 // Optional modules.
Garrick Evans8e8e3472020-01-23 14:03:50 +0900125 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +0900126 // This module is not available in kernels < 3.18
127 "nf_reject_ipv6",
128 // These modules are needed for supporting Chrome traffic on Android
129 // VPN which uses Android's NAT feature. Android NAT sets up
130 // iptables
131 // rules that use these conntrack modules for FTP/TFTP.
132 "nf_nat_ftp",
133 "nf_nat_tftp",
Hugo Benichia0cde9e2019-12-16 11:57:20 +0900134 // The tun module is needed by the Android 464xlat clatd process.
135 "tun",
Garrick Evansa34b5862019-11-20 09:34:01 +0900136 }) != 0) {
137 LOG(WARNING) << "One or more optional kernel modules failed to load.";
138 }
139
Garrick Evans6d227b92019-12-03 16:11:29 +0900140 // This is only needed for CTS (b/27932574).
Hugo Benichi0781d402021-02-22 13:43:11 +0900141 SetSysfsOwnerToAndroidRoot(pid, "xt_idletimer");
Garrick Evans6d227b92019-12-03 16:11:29 +0900142
Garrick Evansa34b5862019-11-20 09:34:01 +0900143 done = true;
144}
145
Hugo Benichif0f10c72020-07-09 10:42:45 +0900146// Returns the ARC management device used for VPN forwarding, ADB-over-TCP.
147std::unique_ptr<Device> MakeArcDevice(AddressManager* addr_mgr,
148 GuestMessage::GuestType guest) {
149 auto ipv4_subnet = addr_mgr->AllocateIPv4Subnet(AddressManager::Guest::ARC);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900150 if (!ipv4_subnet) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900151 LOG(ERROR) << "Subnet already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900152 return nullptr;
153 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900154
Garrick Evanse94b6de2020-02-20 09:19:13 +0900155 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
156 if (!host_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900157 LOG(ERROR) << "Bridge address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900158 return nullptr;
159 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900160
Garrick Evanse94b6de2020-02-20 09:19:13 +0900161 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
162 if (!guest_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900163 LOG(ERROR) << "ARC address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900164 return nullptr;
165 }
166
Hugo Benichif0f10c72020-07-09 10:42:45 +0900167 int subnet_index = (guest == GuestMessage::ARC_VM) ? 1 : kAnySubnetIndex;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900168
Hugo Benichif0f10c72020-07-09 10:42:45 +0900169 auto config = std::make_unique<Device::Config>(
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900170 addr_mgr->GenerateMacAddress(subnet_index), std::move(ipv4_subnet),
171 std::move(host_ipv4_addr), std::move(guest_ipv4_addr));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900172
Hugo Benichif0f10c72020-07-09 10:42:45 +0900173 Device::Options opts{
174 .fwd_multicast = false,
175 .ipv6_enabled = false,
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900176 .adb_allowed = false,
Hugo Benichif0f10c72020-07-09 10:42:45 +0900177 };
178
179 return std::make_unique<Device>(kArcIfname, kArcBridge, kArcIfname,
180 std::move(config), opts);
181}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900182} // namespace
183
Garrick Evans69b85872020-02-04 11:40:26 +0900184ArcService::ArcService(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900185 Datapath* datapath,
186 AddressManager* addr_mgr,
Garrick Evans209a80a2020-11-30 14:42:40 +0900187 GuestMessage::GuestType guest,
188 Device::ChangeEventHandler device_changed_handler)
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900189 : shill_client_(shill_client),
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900190 datapath_(datapath),
191 addr_mgr_(addr_mgr),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900192 guest_(guest),
Garrick Evans209a80a2020-11-30 14:42:40 +0900193 device_changed_handler_(device_changed_handler),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900194 id_(kInvalidId) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900195 arc_device_ = MakeArcDevice(addr_mgr, guest_);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900196 AllocateAddressConfigs();
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900197 shill_client_->RegisterDevicesChangedHandler(
198 base::Bind(&ArcService::OnDevicesChanged, weak_factory_.GetWeakPtr()));
Jie Jiang84c76a12020-04-17 16:45:20 +0900199 shill_client_->ScanDevices();
Garrick Evansf29f5a32019-12-06 11:34:25 +0900200}
201
202ArcService::~ArcService() {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900203 if (IsStarted()) {
204 Stop(id_);
Garrick Evans664a82f2019-12-17 12:18:05 +0900205 }
Garrick Evans54861622019-07-19 09:05:09 +0900206}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900207
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900208bool ArcService::IsStarted() const {
209 return id_ != kInvalidId;
210}
211
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900212void ArcService::AllocateAddressConfigs() {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900213 // The first usable subnet is the "other" ARC device subnet.
Garrick Evansc7071122020-04-17 12:31:57 +0900214 // As a temporary workaround, for ARCVM, allocate fixed MAC addresses.
215 uint8_t mac_addr_index = 2;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900216 // Allocate 2 subnets each for Ethernet and WiFi and 1 for LTE WAN interfaces.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900217 for (const auto type :
218 {ShillClient::Device::Type::kEthernet,
219 ShillClient::Device::Type::kEthernet, ShillClient::Device::Type::kWifi,
220 ShillClient::Device::Type::kWifi,
221 ShillClient::Device::Type::kCellular}) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900222 auto ipv4_subnet =
223 addr_mgr_->AllocateIPv4Subnet(AddressManager::Guest::ARC_NET);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900224 if (!ipv4_subnet) {
225 LOG(ERROR) << "Subnet already in use or unavailable";
226 continue;
227 }
228 // For here out, use the same slices.
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900229 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
230 if (!host_ipv4_addr) {
231 LOG(ERROR) << "Bridge address already in use or unavailable";
232 continue;
233 }
234 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
235 if (!guest_ipv4_addr) {
236 LOG(ERROR) << "ARC address already in use or unavailable";
237 continue;
238 }
239
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900240 MacAddress mac_addr = (guest_ == GuestMessage::ARC_VM)
Garrick Evansc7071122020-04-17 12:31:57 +0900241 ? addr_mgr_->GenerateMacAddress(mac_addr_index++)
242 : addr_mgr_->GenerateMacAddress();
Hugo Benichi84d96c42021-02-26 14:20:13 +0900243 available_configs_[type].emplace_back(std::make_unique<Device::Config>(
Garrick Evansc7071122020-04-17 12:31:57 +0900244 mac_addr, std::move(ipv4_subnet), std::move(host_ipv4_addr),
245 std::move(guest_ipv4_addr)));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900246 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900247
Hugo Benichi84d96c42021-02-26 14:20:13 +0900248 all_configs_.push_back(&arc_device_->config());
249 // Iterate over |available_configs_| with a fixed explicit order and do not
250 // rely on the implicit ordering derived from key values.
251 for (const auto type :
252 {ShillClient::Device::Type::kEthernet, ShillClient::Device::Type::kWifi,
253 ShillClient::Device::Type::kCellular}) {
254 for (const auto& c : available_configs_[type]) {
255 all_configs_.push_back(c.get());
256 }
257 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900258}
259
260std::unique_ptr<Device::Config> ArcService::AcquireConfig(
Hugo Benichi84d96c42021-02-26 14:20:13 +0900261 ShillClient::Device::Type type) {
262 // Normalize shill Device types for different ethernet flavors.
263 if (type == ShillClient::Device::Type::kEthernetEap)
264 type = ShillClient::Device::Type::kEthernet;
265
266 auto it = available_configs_.find(type);
267 if (it == available_configs_.end()) {
268 LOG(ERROR) << "Unsupported shill Device type " << type;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900269 return nullptr;
270 }
271
Hugo Benichi84d96c42021-02-26 14:20:13 +0900272 if (it->second.empty()) {
273 LOG(ERROR)
274 << "Cannot make virtual device: No more addresses available for type "
275 << type;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900276 return nullptr;
277 }
Hugo Benichi84d96c42021-02-26 14:20:13 +0900278
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900279 std::unique_ptr<Device::Config> config;
Hugo Benichi84d96c42021-02-26 14:20:13 +0900280 config = std::move(it->second.front());
281 it->second.pop_front();
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900282 return config;
283}
284
Hugo Benichi84d96c42021-02-26 14:20:13 +0900285void ArcService::ReleaseConfig(ShillClient::Device::Type type,
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900286 std::unique_ptr<Device::Config> config) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900287 available_configs_[type].push_front(std::move(config));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900288}
289
Garrick Evans015b0d62020-02-07 09:06:38 +0900290bool ArcService::Start(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900291 if (IsStarted()) {
292 LOG(WARNING) << "Already running - did something crash?"
293 << " Stopping and restarting...";
294 Stop(id_);
Garrick Evansa51d0a12019-11-28 13:51:23 +0900295 }
296
Hugo Benichif0f10c72020-07-09 10:42:45 +0900297 std::string arc_device_ifname;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900298 if (guest_ == GuestMessage::ARC_VM) {
Hugo Benichi8e448422020-07-07 10:49:00 +0900299 // Allocate TAP devices for all configs.
300 for (auto* config : all_configs_) {
301 auto mac = config->mac_addr();
302 auto tap = datapath_->AddTAP("" /* auto-generate name */, &mac,
303 nullptr /* no ipv4 subnet */,
304 vm_tools::kCrosVmUser);
305 if (tap.empty()) {
306 LOG(ERROR) << "Failed to create TAP device";
307 continue;
308 }
309
310 config->set_tap_ifname(tap);
311 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900312 arc_device_ifname = arc_device_->config().tap_ifname();
Garrick Evans2961c7c2020-04-03 11:34:40 +0900313 } else {
Hugo Benichi0781d402021-02-22 13:43:11 +0900314 OneTimeContainerSetup(*datapath_, id);
Hugo Benichi33860d72020-07-09 16:34:01 +0900315 if (!datapath_->NetnsAttachName(kArcNetnsName, id)) {
316 LOG(ERROR) << "Failed to attach name " << kArcNetnsName << " to pid "
317 << id;
318 return false;
319 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900320 arc_device_ifname = ArcVethHostName(arc_device_->guest_ifname());
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900321 if (!datapath_->ConnectVethPair(id, kArcNetnsName, arc_device_ifname,
322 arc_device_->guest_ifname(),
323 arc_device_->config().mac_addr(),
324 arc_device_->config().guest_ipv4_addr(), 30,
325 arc_device_->options().fwd_multicast)) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900326 LOG(ERROR) << "Cannot create virtual link for device "
327 << arc_device_->phys_ifname();
328 return false;
329 }
Hugo Benichi40fbf0b2021-01-20 19:44:15 +0900330 // Allow netd to write to /sys/class/net/arc0/mtu (b/175571457).
Hugo Benichi0781d402021-02-22 13:43:11 +0900331 SetSysfsOwnerToAndroidRoot(id,
332 "net/" + arc_device_->guest_ifname() + "/mtu");
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900333 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900334 id_ = id;
335
336 // Create the bridge for the management device arc0.
337 // Per crbug/1008686 this device cannot be deleted and then re-added.
338 // So instead of removing the bridge when the service stops, bring down the
339 // device instead and re-up it on restart.
340 if (!datapath_->AddBridge(kArcBridge, arc_device_->config().host_ipv4_addr(),
341 30) &&
342 !datapath_->MaskInterfaceFlags(kArcBridge, IFF_UP)) {
343 LOG(ERROR) << "Failed to bring up arc bridge " << kArcBridge;
344 return false;
345 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900346
347 if (!datapath_->AddToBridge(kArcBridge, arc_device_ifname)) {
348 LOG(ERROR) << "Failed to bridge arc device " << arc_device_ifname << " to "
349 << kArcBridge;
350 return false;
351 }
Hugo Benichi33860d72020-07-09 16:34:01 +0900352 LOG(INFO) << "Started ARC management device " << *arc_device_.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900353
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900354 // Start already known Shill <-> ARC mapped devices.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900355 for (const auto& [ifname, type] : shill_devices_)
356 AddDevice(ifname, type);
Garrick Evanscb791e72019-11-11 15:44:34 +0900357
Garrick Evansf29f5a32019-12-06 11:34:25 +0900358 return true;
Garrick Evanscb791e72019-11-11 15:44:34 +0900359}
360
Garrick Evans015b0d62020-02-07 09:06:38 +0900361void ArcService::Stop(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900362 if (!IsStarted()) {
363 LOG(ERROR) << "ArcService was not running";
364 return;
365 }
366
367 // After the ARC container has stopped, the pid is not known anymore.
368 if (guest_ == GuestMessage::ARC_VM && id_ != id) {
369 LOG(ERROR) << "Mismatched ARCVM CIDs " << id_ << " != " << id;
370 return;
371 }
372
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900373 // Stop Shill <-> ARC mapped devices.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900374 for (const auto& [ifname, type] : shill_devices_)
375 RemoveDevice(ifname, type);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900376
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900377 // Per crbug/1008686 this device cannot be deleted and then re-added.
378 // So instead of removing the bridge, bring it down and mark it. This will
379 // allow us to detect if the device is re-added in case of a crash restart
380 // and do the right thing.
381 if (!datapath_->MaskInterfaceFlags(kArcBridge, IFF_DEBUG, IFF_UP))
382 LOG(ERROR) << "Failed to bring down arc bridge "
383 << "- it may not restart correctly";
384
Hugo Benichi33860d72020-07-09 16:34:01 +0900385 if (guest_ == GuestMessage::ARC) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900386 datapath_->RemoveInterface(ArcVethHostName(arc_device_->phys_ifname()));
Hugo Benichi33860d72020-07-09 16:34:01 +0900387 if (!datapath_->NetnsDeleteName(kArcNetnsName))
388 LOG(WARNING) << "Failed to delete netns name " << kArcNetnsName;
Hugo Benichif0f10c72020-07-09 10:42:45 +0900389 }
390
391 // Destroy allocated TAP devices if any, including the ARC management device.
392 for (auto* config : all_configs_) {
393 if (config->tap_ifname().empty())
394 continue;
395 datapath_->RemoveInterface(config->tap_ifname());
396 config->set_tap_ifname("");
Hugo Benichi33860d72020-07-09 16:34:01 +0900397 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900398
Hugo Benichi33860d72020-07-09 16:34:01 +0900399 LOG(INFO) << "Stopped ARC management device " << *arc_device_.get();
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900400 id_ = kInvalidId;
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900401}
402
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900403void ArcService::OnDevicesChanged(const std::set<std::string>& added,
404 const std::set<std::string>& removed) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900405 for (const std::string& ifname : removed) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900406 RemoveDevice(ifname, shill_devices_[ifname]);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900407 shill_devices_.erase(ifname);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900408 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900409
Hugo Benichif0f10c72020-07-09 10:42:45 +0900410 for (const std::string& ifname : added) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900411 ShillClient::Device shill_device;
412 if (!shill_client_->GetDeviceProperties(ifname, &shill_device)) {
413 LOG(ERROR) << "Could not read shill Device properties for " << ifname;
414 continue;
415 }
416 shill_devices_[ifname] = shill_device.type;
417 AddDevice(ifname, shill_device.type);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900418 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900419}
420
Hugo Benichi84d96c42021-02-26 14:20:13 +0900421void ArcService::AddDevice(const std::string& ifname,
422 ShillClient::Device::Type type) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900423 if (!IsStarted())
424 return;
425
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900426 if (ifname.empty())
427 return;
428
429 if (devices_.find(ifname) != devices_.end()) {
430 LOG(DFATAL) << "Attemping to add already tracked device: " << ifname;
431 return;
432 }
433
434 Device::Options opts{
435 .fwd_multicast = IsMulticastInterface(ifname),
Hugo Benichi84d96c42021-02-26 14:20:13 +0900436 .ipv6_enabled = IsIPv6NDProxyEnabled(type),
437 .adb_allowed = IsAdbAllowed(type),
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900438 };
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900439
Hugo Benichi84d96c42021-02-26 14:20:13 +0900440 auto config = AcquireConfig(type);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900441 if (!config) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900442 LOG(ERROR) << "Cannot acquire a Config for " << ifname;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900443 return;
444 }
445
Garrick Evans8a067562020-05-11 12:47:30 +0900446 auto device = std::make_unique<Device>(ifname, ArcBridgeName(ifname), ifname,
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900447 std::move(config), opts);
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900448 LOG(INFO) << "Starting device " << *device;
Garrick Evans54861622019-07-19 09:05:09 +0900449
450 // Create the bridge.
Hugo Benichif0f10c72020-07-09 10:42:45 +0900451 if (!datapath_->AddBridge(device->host_ifname(),
452 device->config().host_ipv4_addr(), 30)) {
453 LOG(ERROR) << "Failed to setup bridge " << device->host_ifname();
Garrick Evanse94b6de2020-02-20 09:19:13 +0900454 return;
Garrick Evans54861622019-07-19 09:05:09 +0900455 }
456
Hugo Benichi8d622b52020-08-13 15:24:12 +0900457 datapath_->StartRoutingDevice(device->phys_ifname(), device->host_ifname(),
458 device->config().guest_ipv4_addr(),
Hugo Benichi93306e52020-12-04 16:08:00 +0900459 TrafficSource::ARC, false /*route_on_vpn*/);
Garrick Evans2c263102019-07-26 16:07:18 +0900460
Hugo Benichicf904022020-07-07 09:21:58 +0900461 std::string virtual_device_ifname;
462 if (guest_ == GuestMessage::ARC_VM) {
463 virtual_device_ifname = device->config().tap_ifname();
464 if (virtual_device_ifname.empty()) {
465 LOG(ERROR) << "No TAP device for " << *device;
466 return;
467 }
468 } else {
469 virtual_device_ifname = ArcVethHostName(device->guest_ifname());
470 if (!datapath_->ConnectVethPair(
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900471 id_, kArcNetnsName, virtual_device_ifname, device->guest_ifname(),
Hugo Benichicf904022020-07-07 09:21:58 +0900472 device->config().mac_addr(), device->config().guest_ipv4_addr(), 30,
473 device->options().fwd_multicast)) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900474 LOG(ERROR) << "Cannot create veth link for device " << *device;
Hugo Benichicf904022020-07-07 09:21:58 +0900475 return;
476 }
Hugo Benichi6c0233e2020-10-06 22:37:57 +0900477 // Allow netd to write to /sys/class/net/<guest_ifname>/mtu (b/169936104).
Hugo Benichi0781d402021-02-22 13:43:11 +0900478 SetSysfsOwnerToAndroidRoot(id_, "net/" + device->guest_ifname() + "/mtu");
Hugo Benichicf904022020-07-07 09:21:58 +0900479 }
480
481 if (!datapath_->AddToBridge(device->host_ifname(), virtual_device_ifname)) {
482 if (guest_ == GuestMessage::ARC) {
483 datapath_->RemoveInterface(virtual_device_ifname);
484 }
485 LOG(ERROR) << "Failed to bridge interface " << virtual_device_ifname;
Hugo Benichi4833fda2020-07-06 14:56:56 +0900486 return;
487 }
488
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900489 if (device->options().adb_allowed &&
490 !datapath_->AddAdbPortAccessRule(ifname)) {
491 LOG(ERROR) << "Failed to add ADB port access rule";
492 }
493
Garrick Evans209a80a2020-11-30 14:42:40 +0900494 device_changed_handler_.Run(*device, Device::ChangeEvent::ADDED, guest_);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900495 devices_.emplace(ifname, std::move(device));
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900496}
497
Hugo Benichi84d96c42021-02-26 14:20:13 +0900498void ArcService::RemoveDevice(const std::string& ifname,
499 ShillClient::Device::Type type) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900500 if (!IsStarted())
501 return;
502
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900503 const auto it = devices_.find(ifname);
504 if (it == devices_.end()) {
505 LOG(WARNING) << "Unknown device: " << ifname;
Garrick Evanscb791e72019-11-11 15:44:34 +0900506 return;
507 }
508
Hugo Benichif0f10c72020-07-09 10:42:45 +0900509 const auto* device = it->second.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900510 LOG(INFO) << "Removing device " << *device;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900511
Garrick Evans209a80a2020-11-30 14:42:40 +0900512 device_changed_handler_.Run(*device, Device::ChangeEvent::REMOVED, guest_);
513
Hugo Benichif0f10c72020-07-09 10:42:45 +0900514 // ARCVM TAP devices are removed in VmImpl::Stop() when the service stops
Hugo Benichi4833fda2020-07-06 14:56:56 +0900515 if (guest_ == GuestMessage::ARC)
516 datapath_->RemoveInterface(ArcVethHostName(device->phys_ifname()));
Garrick Evans54861622019-07-19 09:05:09 +0900517
Hugo Benichi8d622b52020-08-13 15:24:12 +0900518 datapath_->StopRoutingDevice(device->phys_ifname(), device->host_ifname(),
519 device->config().guest_ipv4_addr(),
Hugo Benichi93306e52020-12-04 16:08:00 +0900520 TrafficSource::ARC, false /*route_on_vpn*/);
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900521 datapath_->RemoveBridge(device->host_ifname());
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900522 if (device->options().adb_allowed)
523 datapath_->DeleteAdbPortAccessRule(ifname);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900524
Hugo Benichi84d96c42021-02-26 14:20:13 +0900525 // Once the physical Device is gone it may not be possible to retrieve
526 // the device type from Shill DBus interface by interface name.
527 ReleaseConfig(type, it->second->release_config());
Hugo Benichif0f10c72020-07-09 10:42:45 +0900528 devices_.erase(it);
Garrick Evanscb791e72019-11-11 15:44:34 +0900529}
530
Garrick Evans38b25a42020-04-06 15:17:42 +0900531std::vector<const Device::Config*> ArcService::GetDeviceConfigs() const {
Hugo Benichi8e448422020-07-07 10:49:00 +0900532 std::vector<const Device::Config*> configs;
533 for (auto* c : all_configs_)
534 configs.emplace_back(c);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900535
Hugo Benichi8e448422020-07-07 10:49:00 +0900536 return configs;
Garrick Evanse94b6de2020-02-20 09:19:13 +0900537}
Garrick Evans02e6e872020-11-30 11:53:13 +0900538
539void ArcService::ScanDevices(
540 base::RepeatingCallback<void(const Device&)> callback) const {
541 for (const auto& [_, d] : devices_)
542 callback.Run(*d.get());
543}
544
Garrick Evans3388a032020-03-24 11:25:55 +0900545} // namespace patchpanel