blob: b4b70df364813c970d1f12c7082cbcfd010d124a [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 Evans6e4eb3b2020-03-09 07:18:31 +09009#include <sys/ioctl.h>
Garrick Evans71e4a862020-05-18 12:22:23 +090010#include <sys/utsname.h>
Garrick Evans54861622019-07-19 09:05:09 +090011
Hugo Benichi84d96c42021-02-26 14:20:13 +090012#include <set>
Garrick Evans5d55f5e2019-07-17 15:28:10 +090013#include <utility>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090014#include <vector>
Garrick Evans5d55f5e2019-07-17 15:28:10 +090015
Garrick Evans54861622019-07-19 09:05:09 +090016#include <base/bind.h>
Garrick Evans5d55f5e2019-07-17 15:28:10 +090017#include <base/files/file_path.h>
18#include <base/files/file_util.h>
19#include <base/logging.h>
20#include <base/strings/string_number_conversions.h>
Qijiang Fan2d7aeb42020-05-19 02:06:39 +090021#include <base/system/sys_info.h>
Garrick Evans1f5a3612019-11-08 12:59:03 +090022#include <brillo/key_value_store.h>
Garrick Evansb4eb3892019-11-13 12:07:07 +090023#include <chromeos/constants/vm_tools.h>
Garrick Evans54861622019-07-19 09:05:09 +090024
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +090025#include "patchpanel/adb_proxy.h"
Garrick Evans3388a032020-03-24 11:25:55 +090026#include "patchpanel/datapath.h"
27#include "patchpanel/mac_address_generator.h"
28#include "patchpanel/manager.h"
29#include "patchpanel/minijailed_process_runner.h"
30#include "patchpanel/net_util.h"
31#include "patchpanel/scoped_ns.h"
Garrick Evans5d55f5e2019-07-17 15:28:10 +090032
Garrick Evans3388a032020-03-24 11:25:55 +090033namespace patchpanel {
Garrick Evans5d55f5e2019-07-17 15:28:10 +090034namespace {
Hugo Benichi0781d402021-02-22 13:43:11 +090035// UID of Android root, relative to the host pid namespace.
Hugo Benichi6c0233e2020-10-06 22:37:57 +090036const int32_t kAndroidRootUid = 655360;
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +090037constexpr uint32_t kInvalidId = 0;
Hugo Benichi33860d72020-07-09 16:34:01 +090038constexpr char kArcNetnsName[] = "arc_netns";
Garrick Evanse94b6de2020-02-20 09:19:13 +090039constexpr char kArcIfname[] = "arc0";
Hugo Benichi84d96c42021-02-26 14:20:13 +090040
41bool IsAdbAllowed(ShillClient::Device::Type type) {
42 static const std::set<ShillClient::Device::Type> adb_allowed_types{
43 ShillClient::Device::Type::kEthernet,
44 ShillClient::Device::Type::kEthernetEap,
45 ShillClient::Device::Type::kWifi,
46 };
47 return adb_allowed_types.find(type) != adb_allowed_types.end();
48}
49
50bool IsIPv6NDProxyEnabled(ShillClient::Device::Type type) {
51 static const std::set<ShillClient::Device::Type> ndproxy_allowed_types{
52 ShillClient::Device::Type::kCellular,
53 ShillClient::Device::Type::kEthernet,
54 ShillClient::Device::Type::kEthernetEap,
55 ShillClient::Device::Type::kWifi,
56 };
57 return ndproxy_allowed_types.find(type) != ndproxy_allowed_types.end();
58}
Garrick Evans54861622019-07-19 09:05:09 +090059
Garrick Evans71e4a862020-05-18 12:22:23 +090060bool KernelVersion(int* major, int* minor) {
61 struct utsname u;
62 if (uname(&u) != 0) {
63 PLOG(ERROR) << "uname failed";
64 *major = *minor = 0;
65 return false;
66 }
67 int unused;
68 if (sscanf(u.release, "%d.%d.%d", major, minor, &unused) != 3) {
69 LOG(ERROR) << "unexpected release string: " << u.release;
70 *major = *minor = 0;
71 return false;
72 }
73 return true;
74}
75
Hugo Benichi0781d402021-02-22 13:43:11 +090076// Makes Android root the owner of /sys/class/ + |path|. |pid| is the ARC
77// container pid.
78void SetSysfsOwnerToAndroidRoot(uint32_t pid, const std::string& path) {
79 ScopedNS ns(pid, ScopedNS::Type::Mount);
80 if (!ns.IsValid()) {
81 LOG(ERROR) << "Cannot enter mnt namespace for pid " << pid;
82 return;
83 }
84
85 const std::string sysfs_path = "/sys/class/" + path;
86 if (chown(sysfs_path.c_str(), kAndroidRootUid, kAndroidRootUid) == -1)
87 PLOG(ERROR) << "Failed to change ownership of " + sysfs_path;
88}
89
90void OneTimeContainerSetup(const Datapath& datapath, uint32_t pid) {
Garrick Evansa34b5862019-11-20 09:34:01 +090091 static bool done = false;
92 if (done)
93 return;
94
Garrick Evans6d227b92019-12-03 16:11:29 +090095 auto& runner = datapath.runner();
96
97 // Load networking modules needed by Android that are not compiled in the
98 // kernel. Android does not allow auto-loading of kernel modules.
Garrick Evansc53b9702020-05-13 13:20:09 +090099 // Expected for all kernels.
Garrick Evans8e8e3472020-01-23 14:03:50 +0900100 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +0900101 // The netfilter modules needed by netd for iptables commands.
102 "ip6table_filter",
103 "ip6t_ipv6header",
104 "ip6t_REJECT",
Garrick Evansa34b5862019-11-20 09:34:01 +0900105 // The ipsec modules for AH and ESP encryption for ipv6.
106 "ah6",
107 "esp6",
108 }) != 0) {
109 LOG(ERROR) << "One or more required kernel modules failed to load."
110 << " Some Android functionality may be broken.";
111 }
Garrick Evansc53b9702020-05-13 13:20:09 +0900112 // The xfrm modules needed for Android's ipsec APIs on kernels < 5.4.
Garrick Evans71e4a862020-05-18 12:22:23 +0900113 int major, minor;
114 if (KernelVersion(&major, &minor) &&
115 (major < 5 || (major == 5 && minor < 4)) &&
116 runner.modprobe_all({
117 "xfrm4_mode_transport",
118 "xfrm4_mode_tunnel",
119 "xfrm6_mode_transport",
120 "xfrm6_mode_tunnel",
121 }) != 0) {
Garrick Evansc53b9702020-05-13 13:20:09 +0900122 LOG(ERROR) << "One or more required kernel modules failed to load."
123 << " Some Android functionality may be broken.";
124 }
125
Garrick Evansa34b5862019-11-20 09:34:01 +0900126 // Optional modules.
Garrick Evans8e8e3472020-01-23 14:03:50 +0900127 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +0900128 // This module is not available in kernels < 3.18
129 "nf_reject_ipv6",
130 // These modules are needed for supporting Chrome traffic on Android
131 // VPN which uses Android's NAT feature. Android NAT sets up
132 // iptables
133 // rules that use these conntrack modules for FTP/TFTP.
134 "nf_nat_ftp",
135 "nf_nat_tftp",
Hugo Benichia0cde9e2019-12-16 11:57:20 +0900136 // The tun module is needed by the Android 464xlat clatd process.
137 "tun",
Garrick Evansa34b5862019-11-20 09:34:01 +0900138 }) != 0) {
139 LOG(WARNING) << "One or more optional kernel modules failed to load.";
140 }
141
Garrick Evans6d227b92019-12-03 16:11:29 +0900142 // This is only needed for CTS (b/27932574).
Hugo Benichi0781d402021-02-22 13:43:11 +0900143 SetSysfsOwnerToAndroidRoot(pid, "xt_idletimer");
Garrick Evans6d227b92019-12-03 16:11:29 +0900144
Garrick Evansa34b5862019-11-20 09:34:01 +0900145 done = true;
146}
147
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900148bool IsMulticastInterface(const std::string& ifname) {
149 if (ifname.empty()) {
150 return false;
151 }
152
153 int fd = socket(AF_INET, SOCK_DGRAM, 0);
154 if (fd < 0) {
155 // If IPv4 fails, try to open a socket using IPv6.
156 fd = socket(AF_INET6, SOCK_DGRAM, 0);
157 if (fd < 0) {
158 LOG(ERROR) << "Unable to create socket";
159 return false;
160 }
161 }
162
163 struct ifreq ifr;
164 memset(&ifr, 0, sizeof(ifr));
165 strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ);
166 if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
167 PLOG(ERROR) << "SIOCGIFFLAGS failed for " << ifname;
168 close(fd);
169 return false;
170 }
171
172 close(fd);
173 return (ifr.ifr_flags & IFF_MULTICAST);
174}
175
Hugo Benichif0f10c72020-07-09 10:42:45 +0900176// Returns the ARC management device used for VPN forwarding, ADB-over-TCP.
177std::unique_ptr<Device> MakeArcDevice(AddressManager* addr_mgr,
178 GuestMessage::GuestType guest) {
179 auto ipv4_subnet = addr_mgr->AllocateIPv4Subnet(AddressManager::Guest::ARC);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900180 if (!ipv4_subnet) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900181 LOG(ERROR) << "Subnet already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900182 return nullptr;
183 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900184
Garrick Evanse94b6de2020-02-20 09:19:13 +0900185 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
186 if (!host_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900187 LOG(ERROR) << "Bridge address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900188 return nullptr;
189 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900190
Garrick Evanse94b6de2020-02-20 09:19:13 +0900191 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
192 if (!guest_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900193 LOG(ERROR) << "ARC address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900194 return nullptr;
195 }
196
Hugo Benichif0f10c72020-07-09 10:42:45 +0900197 int subnet_index = (guest == GuestMessage::ARC_VM) ? 1 : kAnySubnetIndex;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900198
Hugo Benichif0f10c72020-07-09 10:42:45 +0900199 auto config = std::make_unique<Device::Config>(
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900200 addr_mgr->GenerateMacAddress(subnet_index), std::move(ipv4_subnet),
201 std::move(host_ipv4_addr), std::move(guest_ipv4_addr));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900202
Hugo Benichif0f10c72020-07-09 10:42:45 +0900203 Device::Options opts{
204 .fwd_multicast = false,
205 .ipv6_enabled = false,
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900206 .adb_allowed = false,
Hugo Benichif0f10c72020-07-09 10:42:45 +0900207 };
208
209 return std::make_unique<Device>(kArcIfname, kArcBridge, kArcIfname,
210 std::move(config), opts);
211}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900212} // namespace
213
Garrick Evans69b85872020-02-04 11:40:26 +0900214ArcService::ArcService(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900215 Datapath* datapath,
216 AddressManager* addr_mgr,
Garrick Evansf5862122020-03-16 09:13:45 +0900217 TrafficForwarder* forwarder,
Garrick Evans209a80a2020-11-30 14:42:40 +0900218 GuestMessage::GuestType guest,
219 Device::ChangeEventHandler device_changed_handler)
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900220 : shill_client_(shill_client),
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900221 datapath_(datapath),
222 addr_mgr_(addr_mgr),
Garrick Evansf5862122020-03-16 09:13:45 +0900223 forwarder_(forwarder),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900224 guest_(guest),
Garrick Evans209a80a2020-11-30 14:42:40 +0900225 device_changed_handler_(device_changed_handler),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900226 id_(kInvalidId) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900227 arc_device_ = MakeArcDevice(addr_mgr, guest_);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900228 AllocateAddressConfigs();
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900229 shill_client_->RegisterDevicesChangedHandler(
230 base::Bind(&ArcService::OnDevicesChanged, weak_factory_.GetWeakPtr()));
Jie Jiang84c76a12020-04-17 16:45:20 +0900231 shill_client_->ScanDevices();
Garrick Evansf29f5a32019-12-06 11:34:25 +0900232}
233
234ArcService::~ArcService() {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900235 if (IsStarted()) {
236 Stop(id_);
Garrick Evans664a82f2019-12-17 12:18:05 +0900237 }
Garrick Evans54861622019-07-19 09:05:09 +0900238}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900239
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900240bool ArcService::IsStarted() const {
241 return id_ != kInvalidId;
242}
243
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900244void ArcService::AllocateAddressConfigs() {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900245 // The first usable subnet is the "other" ARC device subnet.
Garrick Evansc7071122020-04-17 12:31:57 +0900246 // As a temporary workaround, for ARCVM, allocate fixed MAC addresses.
247 uint8_t mac_addr_index = 2;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900248 // Allocate 2 subnets each for Ethernet and WiFi and 1 for LTE WAN interfaces.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900249 for (const auto type :
250 {ShillClient::Device::Type::kEthernet,
251 ShillClient::Device::Type::kEthernet, ShillClient::Device::Type::kWifi,
252 ShillClient::Device::Type::kWifi,
253 ShillClient::Device::Type::kCellular}) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900254 auto ipv4_subnet =
255 addr_mgr_->AllocateIPv4Subnet(AddressManager::Guest::ARC_NET);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900256 if (!ipv4_subnet) {
257 LOG(ERROR) << "Subnet already in use or unavailable";
258 continue;
259 }
260 // For here out, use the same slices.
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900261 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
262 if (!host_ipv4_addr) {
263 LOG(ERROR) << "Bridge address already in use or unavailable";
264 continue;
265 }
266 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
267 if (!guest_ipv4_addr) {
268 LOG(ERROR) << "ARC address already in use or unavailable";
269 continue;
270 }
271
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900272 MacAddress mac_addr = (guest_ == GuestMessage::ARC_VM)
Garrick Evansc7071122020-04-17 12:31:57 +0900273 ? addr_mgr_->GenerateMacAddress(mac_addr_index++)
274 : addr_mgr_->GenerateMacAddress();
Hugo Benichi84d96c42021-02-26 14:20:13 +0900275 available_configs_[type].emplace_back(std::make_unique<Device::Config>(
Garrick Evansc7071122020-04-17 12:31:57 +0900276 mac_addr, std::move(ipv4_subnet), std::move(host_ipv4_addr),
277 std::move(guest_ipv4_addr)));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900278 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900279
Hugo Benichi84d96c42021-02-26 14:20:13 +0900280 all_configs_.push_back(&arc_device_->config());
281 // Iterate over |available_configs_| with a fixed explicit order and do not
282 // rely on the implicit ordering derived from key values.
283 for (const auto type :
284 {ShillClient::Device::Type::kEthernet, ShillClient::Device::Type::kWifi,
285 ShillClient::Device::Type::kCellular}) {
286 for (const auto& c : available_configs_[type]) {
287 all_configs_.push_back(c.get());
288 }
289 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900290}
291
292std::unique_ptr<Device::Config> ArcService::AcquireConfig(
Hugo Benichi84d96c42021-02-26 14:20:13 +0900293 ShillClient::Device::Type type) {
294 // Normalize shill Device types for different ethernet flavors.
295 if (type == ShillClient::Device::Type::kEthernetEap)
296 type = ShillClient::Device::Type::kEthernet;
297
298 auto it = available_configs_.find(type);
299 if (it == available_configs_.end()) {
300 LOG(ERROR) << "Unsupported shill Device type " << type;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900301 return nullptr;
302 }
303
Hugo Benichi84d96c42021-02-26 14:20:13 +0900304 if (it->second.empty()) {
305 LOG(ERROR)
306 << "Cannot make virtual device: No more addresses available for type "
307 << type;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900308 return nullptr;
309 }
Hugo Benichi84d96c42021-02-26 14:20:13 +0900310
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900311 std::unique_ptr<Device::Config> config;
Hugo Benichi84d96c42021-02-26 14:20:13 +0900312 config = std::move(it->second.front());
313 it->second.pop_front();
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900314 return config;
315}
316
Hugo Benichi84d96c42021-02-26 14:20:13 +0900317void ArcService::ReleaseConfig(ShillClient::Device::Type type,
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900318 std::unique_ptr<Device::Config> config) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900319 available_configs_[type].push_front(std::move(config));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900320}
321
Garrick Evans015b0d62020-02-07 09:06:38 +0900322bool ArcService::Start(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900323 if (IsStarted()) {
324 LOG(WARNING) << "Already running - did something crash?"
325 << " Stopping and restarting...";
326 Stop(id_);
Garrick Evansa51d0a12019-11-28 13:51:23 +0900327 }
328
Hugo Benichif0f10c72020-07-09 10:42:45 +0900329 std::string arc_device_ifname;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900330 if (guest_ == GuestMessage::ARC_VM) {
Hugo Benichi8e448422020-07-07 10:49:00 +0900331 // Allocate TAP devices for all configs.
332 for (auto* config : all_configs_) {
333 auto mac = config->mac_addr();
334 auto tap = datapath_->AddTAP("" /* auto-generate name */, &mac,
335 nullptr /* no ipv4 subnet */,
336 vm_tools::kCrosVmUser);
337 if (tap.empty()) {
338 LOG(ERROR) << "Failed to create TAP device";
339 continue;
340 }
341
342 config->set_tap_ifname(tap);
343 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900344 arc_device_ifname = arc_device_->config().tap_ifname();
Garrick Evans2961c7c2020-04-03 11:34:40 +0900345 } else {
Hugo Benichi0781d402021-02-22 13:43:11 +0900346 OneTimeContainerSetup(*datapath_, id);
Hugo Benichi33860d72020-07-09 16:34:01 +0900347 if (!datapath_->NetnsAttachName(kArcNetnsName, id)) {
348 LOG(ERROR) << "Failed to attach name " << kArcNetnsName << " to pid "
349 << id;
350 return false;
351 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900352 arc_device_ifname = ArcVethHostName(arc_device_->guest_ifname());
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900353 if (!datapath_->ConnectVethPair(id, kArcNetnsName, arc_device_ifname,
354 arc_device_->guest_ifname(),
355 arc_device_->config().mac_addr(),
356 arc_device_->config().guest_ipv4_addr(), 30,
357 arc_device_->options().fwd_multicast)) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900358 LOG(ERROR) << "Cannot create virtual link for device "
359 << arc_device_->phys_ifname();
360 return false;
361 }
Hugo Benichi40fbf0b2021-01-20 19:44:15 +0900362 // Allow netd to write to /sys/class/net/arc0/mtu (b/175571457).
Hugo Benichi0781d402021-02-22 13:43:11 +0900363 SetSysfsOwnerToAndroidRoot(id,
364 "net/" + arc_device_->guest_ifname() + "/mtu");
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900365 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900366 id_ = id;
367
368 // Create the bridge for the management device arc0.
369 // Per crbug/1008686 this device cannot be deleted and then re-added.
370 // So instead of removing the bridge when the service stops, bring down the
371 // device instead and re-up it on restart.
372 if (!datapath_->AddBridge(kArcBridge, arc_device_->config().host_ipv4_addr(),
373 30) &&
374 !datapath_->MaskInterfaceFlags(kArcBridge, IFF_UP)) {
375 LOG(ERROR) << "Failed to bring up arc bridge " << kArcBridge;
376 return false;
377 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900378
379 if (!datapath_->AddToBridge(kArcBridge, arc_device_ifname)) {
380 LOG(ERROR) << "Failed to bridge arc device " << arc_device_ifname << " to "
381 << kArcBridge;
382 return false;
383 }
Hugo Benichi33860d72020-07-09 16:34:01 +0900384 LOG(INFO) << "Started ARC management device " << *arc_device_.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900385
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900386 // Start already known Shill <-> ARC mapped devices.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900387 for (const auto& [ifname, type] : shill_devices_)
388 AddDevice(ifname, type);
Garrick Evanscb791e72019-11-11 15:44:34 +0900389
Garrick Evansf29f5a32019-12-06 11:34:25 +0900390 return true;
Garrick Evanscb791e72019-11-11 15:44:34 +0900391}
392
Garrick Evans015b0d62020-02-07 09:06:38 +0900393void ArcService::Stop(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900394 if (!IsStarted()) {
395 LOG(ERROR) << "ArcService was not running";
396 return;
397 }
398
399 // After the ARC container has stopped, the pid is not known anymore.
400 if (guest_ == GuestMessage::ARC_VM && id_ != id) {
401 LOG(ERROR) << "Mismatched ARCVM CIDs " << id_ << " != " << id;
402 return;
403 }
404
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900405 // Stop Shill <-> ARC mapped devices.
Hugo Benichi84d96c42021-02-26 14:20:13 +0900406 for (const auto& [ifname, type] : shill_devices_)
407 RemoveDevice(ifname, type);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900408
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900409 // Per crbug/1008686 this device cannot be deleted and then re-added.
410 // So instead of removing the bridge, bring it down and mark it. This will
411 // allow us to detect if the device is re-added in case of a crash restart
412 // and do the right thing.
413 if (!datapath_->MaskInterfaceFlags(kArcBridge, IFF_DEBUG, IFF_UP))
414 LOG(ERROR) << "Failed to bring down arc bridge "
415 << "- it may not restart correctly";
416
Hugo Benichi33860d72020-07-09 16:34:01 +0900417 if (guest_ == GuestMessage::ARC) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900418 datapath_->RemoveInterface(ArcVethHostName(arc_device_->phys_ifname()));
Hugo Benichi33860d72020-07-09 16:34:01 +0900419 if (!datapath_->NetnsDeleteName(kArcNetnsName))
420 LOG(WARNING) << "Failed to delete netns name " << kArcNetnsName;
Hugo Benichif0f10c72020-07-09 10:42:45 +0900421 }
422
423 // Destroy allocated TAP devices if any, including the ARC management device.
424 for (auto* config : all_configs_) {
425 if (config->tap_ifname().empty())
426 continue;
427 datapath_->RemoveInterface(config->tap_ifname());
428 config->set_tap_ifname("");
Hugo Benichi33860d72020-07-09 16:34:01 +0900429 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900430
Hugo Benichi33860d72020-07-09 16:34:01 +0900431 LOG(INFO) << "Stopped ARC management device " << *arc_device_.get();
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900432 id_ = kInvalidId;
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900433}
434
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900435void ArcService::OnDevicesChanged(const std::set<std::string>& added,
436 const std::set<std::string>& removed) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900437 for (const std::string& ifname : removed) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900438 RemoveDevice(ifname, shill_devices_[ifname]);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900439 shill_devices_.erase(ifname);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900440 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900441
Hugo Benichif0f10c72020-07-09 10:42:45 +0900442 for (const std::string& ifname : added) {
Hugo Benichi84d96c42021-02-26 14:20:13 +0900443 ShillClient::Device shill_device;
444 if (!shill_client_->GetDeviceProperties(ifname, &shill_device)) {
445 LOG(ERROR) << "Could not read shill Device properties for " << ifname;
446 continue;
447 }
448 shill_devices_[ifname] = shill_device.type;
449 AddDevice(ifname, shill_device.type);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900450 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900451}
452
Hugo Benichi84d96c42021-02-26 14:20:13 +0900453void ArcService::AddDevice(const std::string& ifname,
454 ShillClient::Device::Type type) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900455 if (!IsStarted())
456 return;
457
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900458 if (ifname.empty())
459 return;
460
461 if (devices_.find(ifname) != devices_.end()) {
462 LOG(DFATAL) << "Attemping to add already tracked device: " << ifname;
463 return;
464 }
465
466 Device::Options opts{
467 .fwd_multicast = IsMulticastInterface(ifname),
Hugo Benichi84d96c42021-02-26 14:20:13 +0900468 .ipv6_enabled = IsIPv6NDProxyEnabled(type),
469 .adb_allowed = IsAdbAllowed(type),
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900470 };
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900471
Hugo Benichi84d96c42021-02-26 14:20:13 +0900472 auto config = AcquireConfig(type);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900473 if (!config) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900474 LOG(ERROR) << "Cannot acquire a Config for " << ifname;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900475 return;
476 }
477
Garrick Evans8a067562020-05-11 12:47:30 +0900478 auto device = std::make_unique<Device>(ifname, ArcBridgeName(ifname), ifname,
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900479 std::move(config), opts);
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900480 LOG(INFO) << "Starting device " << *device;
Garrick Evans54861622019-07-19 09:05:09 +0900481
482 // Create the bridge.
Hugo Benichif0f10c72020-07-09 10:42:45 +0900483 if (!datapath_->AddBridge(device->host_ifname(),
484 device->config().host_ipv4_addr(), 30)) {
485 LOG(ERROR) << "Failed to setup bridge " << device->host_ifname();
Garrick Evanse94b6de2020-02-20 09:19:13 +0900486 return;
Garrick Evans54861622019-07-19 09:05:09 +0900487 }
488
Hugo Benichi8d622b52020-08-13 15:24:12 +0900489 datapath_->StartRoutingDevice(device->phys_ifname(), device->host_ifname(),
490 device->config().guest_ipv4_addr(),
Hugo Benichi93306e52020-12-04 16:08:00 +0900491 TrafficSource::ARC, false /*route_on_vpn*/);
Garrick Evans2c263102019-07-26 16:07:18 +0900492
Hugo Benichicf904022020-07-07 09:21:58 +0900493 std::string virtual_device_ifname;
494 if (guest_ == GuestMessage::ARC_VM) {
495 virtual_device_ifname = device->config().tap_ifname();
496 if (virtual_device_ifname.empty()) {
497 LOG(ERROR) << "No TAP device for " << *device;
498 return;
499 }
500 } else {
501 virtual_device_ifname = ArcVethHostName(device->guest_ifname());
502 if (!datapath_->ConnectVethPair(
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900503 id_, kArcNetnsName, virtual_device_ifname, device->guest_ifname(),
Hugo Benichicf904022020-07-07 09:21:58 +0900504 device->config().mac_addr(), device->config().guest_ipv4_addr(), 30,
505 device->options().fwd_multicast)) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900506 LOG(ERROR) << "Cannot create veth link for device " << *device;
Hugo Benichicf904022020-07-07 09:21:58 +0900507 return;
508 }
Hugo Benichi6c0233e2020-10-06 22:37:57 +0900509 // Allow netd to write to /sys/class/net/<guest_ifname>/mtu (b/169936104).
Hugo Benichi0781d402021-02-22 13:43:11 +0900510 SetSysfsOwnerToAndroidRoot(id_, "net/" + device->guest_ifname() + "/mtu");
Hugo Benichicf904022020-07-07 09:21:58 +0900511 }
512
513 if (!datapath_->AddToBridge(device->host_ifname(), virtual_device_ifname)) {
514 if (guest_ == GuestMessage::ARC) {
515 datapath_->RemoveInterface(virtual_device_ifname);
516 }
517 LOG(ERROR) << "Failed to bridge interface " << virtual_device_ifname;
Hugo Benichi4833fda2020-07-06 14:56:56 +0900518 return;
519 }
520
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900521 if (device->options().adb_allowed &&
522 !datapath_->AddAdbPortAccessRule(ifname)) {
523 LOG(ERROR) << "Failed to add ADB port access rule";
524 }
525
Hugo Benichi4833fda2020-07-06 14:56:56 +0900526 forwarder_->StartForwarding(device->phys_ifname(), device->host_ifname(),
527 device->options().ipv6_enabled,
528 device->options().fwd_multicast);
Garrick Evans209a80a2020-11-30 14:42:40 +0900529 device_changed_handler_.Run(*device, Device::ChangeEvent::ADDED, guest_);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900530 devices_.emplace(ifname, std::move(device));
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900531}
532
Hugo Benichi84d96c42021-02-26 14:20:13 +0900533void ArcService::RemoveDevice(const std::string& ifname,
534 ShillClient::Device::Type type) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900535 if (!IsStarted())
536 return;
537
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900538 const auto it = devices_.find(ifname);
539 if (it == devices_.end()) {
540 LOG(WARNING) << "Unknown device: " << ifname;
Garrick Evanscb791e72019-11-11 15:44:34 +0900541 return;
542 }
543
Hugo Benichif0f10c72020-07-09 10:42:45 +0900544 const auto* device = it->second.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900545 LOG(INFO) << "Removing device " << *device;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900546
Garrick Evans209a80a2020-11-30 14:42:40 +0900547 device_changed_handler_.Run(*device, Device::ChangeEvent::REMOVED, guest_);
548
Hugo Benichi4833fda2020-07-06 14:56:56 +0900549 forwarder_->StopForwarding(device->phys_ifname(), device->host_ifname(),
550 device->options().ipv6_enabled,
551 device->options().fwd_multicast);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900552
553 // ARCVM TAP devices are removed in VmImpl::Stop() when the service stops
Hugo Benichi4833fda2020-07-06 14:56:56 +0900554 if (guest_ == GuestMessage::ARC)
555 datapath_->RemoveInterface(ArcVethHostName(device->phys_ifname()));
Garrick Evans54861622019-07-19 09:05:09 +0900556
Hugo Benichi8d622b52020-08-13 15:24:12 +0900557 datapath_->StopRoutingDevice(device->phys_ifname(), device->host_ifname(),
558 device->config().guest_ipv4_addr(),
Hugo Benichi93306e52020-12-04 16:08:00 +0900559 TrafficSource::ARC, false /*route_on_vpn*/);
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900560 datapath_->RemoveBridge(device->host_ifname());
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900561 if (device->options().adb_allowed)
562 datapath_->DeleteAdbPortAccessRule(ifname);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900563
Hugo Benichi84d96c42021-02-26 14:20:13 +0900564 // Once the physical Device is gone it may not be possible to retrieve
565 // the device type from Shill DBus interface by interface name.
566 ReleaseConfig(type, it->second->release_config());
Hugo Benichif0f10c72020-07-09 10:42:45 +0900567 devices_.erase(it);
Garrick Evanscb791e72019-11-11 15:44:34 +0900568}
569
Garrick Evans38b25a42020-04-06 15:17:42 +0900570std::vector<const Device::Config*> ArcService::GetDeviceConfigs() const {
Hugo Benichi8e448422020-07-07 10:49:00 +0900571 std::vector<const Device::Config*> configs;
572 for (auto* c : all_configs_)
573 configs.emplace_back(c);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900574
Hugo Benichi8e448422020-07-07 10:49:00 +0900575 return configs;
Garrick Evanse94b6de2020-02-20 09:19:13 +0900576}
Garrick Evans02e6e872020-11-30 11:53:13 +0900577
578void ArcService::ScanDevices(
579 base::RepeatingCallback<void(const Device&)> callback) const {
580 for (const auto& [_, d] : devices_)
581 callback.Run(*d.get());
582}
583
Garrick Evans3388a032020-03-24 11:25:55 +0900584} // namespace patchpanel