blob: 690bec35e44c8359b78179a5098491339121c8c3 [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
Garrick Evans5d55f5e2019-07-17 15:28:10 +090012#include <utility>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090013#include <vector>
Garrick Evans5d55f5e2019-07-17 15:28:10 +090014
Garrick Evans54861622019-07-19 09:05:09 +090015#include <base/bind.h>
Garrick Evans5d55f5e2019-07-17 15:28:10 +090016#include <base/files/file_path.h>
17#include <base/files/file_util.h>
18#include <base/logging.h>
19#include <base/strings/string_number_conversions.h>
20#include <base/strings/string_util.h>
Garrick Evans54861622019-07-19 09:05:09 +090021#include <base/strings/stringprintf.h>
Qijiang Fan2d7aeb42020-05-19 02:06:39 +090022#include <base/system/sys_info.h>
Garrick Evans1f5a3612019-11-08 12:59:03 +090023#include <brillo/key_value_store.h>
Garrick Evansb4eb3892019-11-13 12:07:07 +090024#include <chromeos/constants/vm_tools.h>
Garrick Evans54861622019-07-19 09:05:09 +090025
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +090026#include "patchpanel/adb_proxy.h"
Garrick Evans3388a032020-03-24 11:25:55 +090027#include "patchpanel/datapath.h"
28#include "patchpanel/mac_address_generator.h"
29#include "patchpanel/manager.h"
30#include "patchpanel/minijailed_process_runner.h"
31#include "patchpanel/net_util.h"
32#include "patchpanel/scoped_ns.h"
Garrick Evans5d55f5e2019-07-17 15:28:10 +090033
Garrick Evans3388a032020-03-24 11:25:55 +090034namespace patchpanel {
Garrick Evans5d55f5e2019-07-17 15:28:10 +090035namespace {
Hugo Benichi0781d402021-02-22 13:43:11 +090036// UID of Android root, relative to the host pid namespace.
Hugo Benichi6c0233e2020-10-06 22:37:57 +090037const int32_t kAndroidRootUid = 655360;
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +090038constexpr uint32_t kInvalidId = 0;
Hugo Benichi33860d72020-07-09 16:34:01 +090039constexpr char kArcNetnsName[] = "arc_netns";
Garrick Evanse94b6de2020-02-20 09:19:13 +090040constexpr char kArcIfname[] = "arc0";
Garrick Evans6e4eb3b2020-03-09 07:18:31 +090041constexpr std::array<const char*, 2> kEthernetInterfacePrefixes{{"eth", "usb"}};
42constexpr std::array<const char*, 2> kWifiInterfacePrefixes{{"wlan", "mlan"}};
Garrick Evans86c7d9c2020-03-17 09:25:48 +090043constexpr std::array<const char*, 2> kCellInterfacePrefixes{{"wwan", "rmnet"}};
Garrick Evans54861622019-07-19 09:05:09 +090044
Garrick Evans71e4a862020-05-18 12:22:23 +090045bool KernelVersion(int* major, int* minor) {
46 struct utsname u;
47 if (uname(&u) != 0) {
48 PLOG(ERROR) << "uname failed";
49 *major = *minor = 0;
50 return false;
51 }
52 int unused;
53 if (sscanf(u.release, "%d.%d.%d", major, minor, &unused) != 3) {
54 LOG(ERROR) << "unexpected release string: " << u.release;
55 *major = *minor = 0;
56 return false;
57 }
58 return true;
59}
60
Hugo Benichi0781d402021-02-22 13:43:11 +090061// Makes Android root the owner of /sys/class/ + |path|. |pid| is the ARC
62// container pid.
63void SetSysfsOwnerToAndroidRoot(uint32_t pid, const std::string& path) {
64 ScopedNS ns(pid, ScopedNS::Type::Mount);
65 if (!ns.IsValid()) {
66 LOG(ERROR) << "Cannot enter mnt namespace for pid " << pid;
67 return;
68 }
69
70 const std::string sysfs_path = "/sys/class/" + path;
71 if (chown(sysfs_path.c_str(), kAndroidRootUid, kAndroidRootUid) == -1)
72 PLOG(ERROR) << "Failed to change ownership of " + sysfs_path;
73}
74
75void OneTimeContainerSetup(const Datapath& datapath, uint32_t pid) {
Garrick Evansa34b5862019-11-20 09:34:01 +090076 static bool done = false;
77 if (done)
78 return;
79
Garrick Evans6d227b92019-12-03 16:11:29 +090080 auto& runner = datapath.runner();
81
82 // Load networking modules needed by Android that are not compiled in the
83 // kernel. Android does not allow auto-loading of kernel modules.
Garrick Evansc53b9702020-05-13 13:20:09 +090084 // Expected for all kernels.
Garrick Evans8e8e3472020-01-23 14:03:50 +090085 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +090086 // The netfilter modules needed by netd for iptables commands.
87 "ip6table_filter",
88 "ip6t_ipv6header",
89 "ip6t_REJECT",
Garrick Evansa34b5862019-11-20 09:34:01 +090090 // The ipsec modules for AH and ESP encryption for ipv6.
91 "ah6",
92 "esp6",
93 }) != 0) {
94 LOG(ERROR) << "One or more required kernel modules failed to load."
95 << " Some Android functionality may be broken.";
96 }
Garrick Evansc53b9702020-05-13 13:20:09 +090097 // The xfrm modules needed for Android's ipsec APIs on kernels < 5.4.
Garrick Evans71e4a862020-05-18 12:22:23 +090098 int major, minor;
99 if (KernelVersion(&major, &minor) &&
100 (major < 5 || (major == 5 && minor < 4)) &&
101 runner.modprobe_all({
102 "xfrm4_mode_transport",
103 "xfrm4_mode_tunnel",
104 "xfrm6_mode_transport",
105 "xfrm6_mode_tunnel",
106 }) != 0) {
Garrick Evansc53b9702020-05-13 13:20:09 +0900107 LOG(ERROR) << "One or more required kernel modules failed to load."
108 << " Some Android functionality may be broken.";
109 }
110
Garrick Evansa34b5862019-11-20 09:34:01 +0900111 // Optional modules.
Garrick Evans8e8e3472020-01-23 14:03:50 +0900112 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +0900113 // This module is not available in kernels < 3.18
114 "nf_reject_ipv6",
115 // These modules are needed for supporting Chrome traffic on Android
116 // VPN which uses Android's NAT feature. Android NAT sets up
117 // iptables
118 // rules that use these conntrack modules for FTP/TFTP.
119 "nf_nat_ftp",
120 "nf_nat_tftp",
Hugo Benichia0cde9e2019-12-16 11:57:20 +0900121 // The tun module is needed by the Android 464xlat clatd process.
122 "tun",
Garrick Evansa34b5862019-11-20 09:34:01 +0900123 }) != 0) {
124 LOG(WARNING) << "One or more optional kernel modules failed to load.";
125 }
126
Garrick Evans6d227b92019-12-03 16:11:29 +0900127 // This is only needed for CTS (b/27932574).
Hugo Benichi0781d402021-02-22 13:43:11 +0900128 SetSysfsOwnerToAndroidRoot(pid, "xt_idletimer");
Garrick Evans6d227b92019-12-03 16:11:29 +0900129
Garrick Evansa34b5862019-11-20 09:34:01 +0900130 done = true;
131}
132
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900133ArcService::InterfaceType InterfaceTypeFor(const std::string& ifname) {
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900134 for (const auto& prefix : kEthernetInterfacePrefixes) {
135 if (base::StartsWith(ifname, prefix,
136 base::CompareCase::INSENSITIVE_ASCII)) {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900137 return ArcService::InterfaceType::ETHERNET;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900138 }
139 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900140 for (const auto& prefix : kWifiInterfacePrefixes) {
141 if (base::StartsWith(ifname, prefix,
142 base::CompareCase::INSENSITIVE_ASCII)) {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900143 return ArcService::InterfaceType::WIFI;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900144 }
145 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900146 for (const auto& prefix : kCellInterfacePrefixes) {
147 if (base::StartsWith(ifname, prefix,
148 base::CompareCase::INSENSITIVE_ASCII)) {
149 return ArcService::InterfaceType::CELL;
150 }
151 }
152 return ArcService::InterfaceType::UNKNOWN;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900153}
154
155bool IsMulticastInterface(const std::string& ifname) {
156 if (ifname.empty()) {
157 return false;
158 }
159
160 int fd = socket(AF_INET, SOCK_DGRAM, 0);
161 if (fd < 0) {
162 // If IPv4 fails, try to open a socket using IPv6.
163 fd = socket(AF_INET6, SOCK_DGRAM, 0);
164 if (fd < 0) {
165 LOG(ERROR) << "Unable to create socket";
166 return false;
167 }
168 }
169
170 struct ifreq ifr;
171 memset(&ifr, 0, sizeof(ifr));
172 strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ);
173 if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
174 PLOG(ERROR) << "SIOCGIFFLAGS failed for " << ifname;
175 close(fd);
176 return false;
177 }
178
179 close(fd);
180 return (ifr.ifr_flags & IFF_MULTICAST);
181}
182
Hugo Benichif0f10c72020-07-09 10:42:45 +0900183// Returns the ARC management device used for VPN forwarding, ADB-over-TCP.
184std::unique_ptr<Device> MakeArcDevice(AddressManager* addr_mgr,
185 GuestMessage::GuestType guest) {
186 auto ipv4_subnet = addr_mgr->AllocateIPv4Subnet(AddressManager::Guest::ARC);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900187 if (!ipv4_subnet) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900188 LOG(ERROR) << "Subnet already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900189 return nullptr;
190 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900191
Garrick Evanse94b6de2020-02-20 09:19:13 +0900192 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
193 if (!host_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900194 LOG(ERROR) << "Bridge address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900195 return nullptr;
196 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900197
Garrick Evanse94b6de2020-02-20 09:19:13 +0900198 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
199 if (!guest_ipv4_addr) {
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900200 LOG(ERROR) << "ARC address already in use or unavailable";
Garrick Evanse94b6de2020-02-20 09:19:13 +0900201 return nullptr;
202 }
203
Hugo Benichif0f10c72020-07-09 10:42:45 +0900204 int subnet_index = (guest == GuestMessage::ARC_VM) ? 1 : kAnySubnetIndex;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900205
Hugo Benichif0f10c72020-07-09 10:42:45 +0900206 auto config = std::make_unique<Device::Config>(
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900207 addr_mgr->GenerateMacAddress(subnet_index), std::move(ipv4_subnet),
208 std::move(host_ipv4_addr), std::move(guest_ipv4_addr));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900209
Hugo Benichif0f10c72020-07-09 10:42:45 +0900210 Device::Options opts{
211 .fwd_multicast = false,
212 .ipv6_enabled = false,
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900213 .adb_allowed = false,
Hugo Benichif0f10c72020-07-09 10:42:45 +0900214 };
215
216 return std::make_unique<Device>(kArcIfname, kArcBridge, kArcIfname,
217 std::move(config), opts);
218}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900219} // namespace
220
Garrick Evans69b85872020-02-04 11:40:26 +0900221ArcService::ArcService(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900222 Datapath* datapath,
223 AddressManager* addr_mgr,
Garrick Evansf5862122020-03-16 09:13:45 +0900224 TrafficForwarder* forwarder,
Garrick Evans209a80a2020-11-30 14:42:40 +0900225 GuestMessage::GuestType guest,
226 Device::ChangeEventHandler device_changed_handler)
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900227 : shill_client_(shill_client),
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900228 datapath_(datapath),
229 addr_mgr_(addr_mgr),
Garrick Evansf5862122020-03-16 09:13:45 +0900230 forwarder_(forwarder),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900231 guest_(guest),
Garrick Evans209a80a2020-11-30 14:42:40 +0900232 device_changed_handler_(device_changed_handler),
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900233 id_(kInvalidId) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900234 arc_device_ = MakeArcDevice(addr_mgr, guest_);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900235 AllocateAddressConfigs();
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900236 shill_client_->RegisterDevicesChangedHandler(
237 base::Bind(&ArcService::OnDevicesChanged, weak_factory_.GetWeakPtr()));
Jie Jiang84c76a12020-04-17 16:45:20 +0900238 shill_client_->ScanDevices();
Garrick Evansf29f5a32019-12-06 11:34:25 +0900239}
240
241ArcService::~ArcService() {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900242 if (IsStarted()) {
243 Stop(id_);
Garrick Evans664a82f2019-12-17 12:18:05 +0900244 }
Garrick Evans54861622019-07-19 09:05:09 +0900245}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900246
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900247bool ArcService::IsStarted() const {
248 return id_ != kInvalidId;
249}
250
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900251void ArcService::AllocateAddressConfigs() {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900252 // The first usable subnet is the "other" ARC device subnet.
Garrick Evansc7071122020-04-17 12:31:57 +0900253 // As a temporary workaround, for ARCVM, allocate fixed MAC addresses.
254 uint8_t mac_addr_index = 2;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900255 // Allocate 2 subnets each for Ethernet and WiFi and 1 for LTE WAN interfaces.
256 for (const auto itype :
257 {InterfaceType::ETHERNET, InterfaceType::ETHERNET, InterfaceType::WIFI,
258 InterfaceType::WIFI, InterfaceType::CELL}) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900259 auto ipv4_subnet =
260 addr_mgr_->AllocateIPv4Subnet(AddressManager::Guest::ARC_NET);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900261 if (!ipv4_subnet) {
262 LOG(ERROR) << "Subnet already in use or unavailable";
263 continue;
264 }
265 // For here out, use the same slices.
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900266 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
267 if (!host_ipv4_addr) {
268 LOG(ERROR) << "Bridge address already in use or unavailable";
269 continue;
270 }
271 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
272 if (!guest_ipv4_addr) {
273 LOG(ERROR) << "ARC address already in use or unavailable";
274 continue;
275 }
276
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900277 MacAddress mac_addr = (guest_ == GuestMessage::ARC_VM)
Garrick Evansc7071122020-04-17 12:31:57 +0900278 ? addr_mgr_->GenerateMacAddress(mac_addr_index++)
279 : addr_mgr_->GenerateMacAddress();
Hugo Benichi8e448422020-07-07 10:49:00 +0900280 available_configs_[itype].emplace_back(std::make_unique<Device::Config>(
Garrick Evansc7071122020-04-17 12:31:57 +0900281 mac_addr, std::move(ipv4_subnet), std::move(host_ipv4_addr),
282 std::move(guest_ipv4_addr)));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900283 }
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900284
Hugo Benichi8e448422020-07-07 10:49:00 +0900285 for (const auto& kv : available_configs_)
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900286 for (const auto& c : kv.second)
Hugo Benichi8e448422020-07-07 10:49:00 +0900287 all_configs_.emplace_back(c.get());
Hugo Benichif0f10c72020-07-09 10:42:45 +0900288 // Append arc0 config so that the necessary tap device gets created.
289 all_configs_.insert(all_configs_.begin(), &arc_device_->config());
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900290}
291
292std::unique_ptr<Device::Config> ArcService::AcquireConfig(
293 const std::string& ifname) {
294 auto itype = InterfaceTypeFor(ifname);
295 if (itype == InterfaceType::UNKNOWN) {
296 LOG(ERROR) << "Unsupported interface: " << ifname;
297 return nullptr;
298 }
299
Hugo Benichi8e448422020-07-07 10:49:00 +0900300 auto& configs = available_configs_[itype];
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900301 if (configs.empty()) {
302 LOG(ERROR) << "No more addresses available. Cannot make device for "
303 << ifname;
304 return nullptr;
305 }
306 std::unique_ptr<Device::Config> config;
307 config = std::move(configs.front());
308 configs.pop_front();
309 return config;
310}
311
312void ArcService::ReleaseConfig(const std::string& ifname,
313 std::unique_ptr<Device::Config> config) {
314 auto itype = InterfaceTypeFor(ifname);
315 if (itype == InterfaceType::UNKNOWN) {
316 LOG(ERROR) << "Unsupported interface: " << ifname;
317 return;
318 }
319
Hugo Benichi8e448422020-07-07 10:49:00 +0900320 available_configs_[itype].push_front(std::move(config));
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900321}
322
Garrick Evans015b0d62020-02-07 09:06:38 +0900323bool ArcService::Start(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900324 if (IsStarted()) {
325 LOG(WARNING) << "Already running - did something crash?"
326 << " Stopping and restarting...";
327 Stop(id_);
Garrick Evansa51d0a12019-11-28 13:51:23 +0900328 }
329
Hugo Benichif0f10c72020-07-09 10:42:45 +0900330 std::string arc_device_ifname;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900331 if (guest_ == GuestMessage::ARC_VM) {
Hugo Benichi8e448422020-07-07 10:49:00 +0900332 // Allocate TAP devices for all configs.
333 for (auto* config : all_configs_) {
334 auto mac = config->mac_addr();
335 auto tap = datapath_->AddTAP("" /* auto-generate name */, &mac,
336 nullptr /* no ipv4 subnet */,
337 vm_tools::kCrosVmUser);
338 if (tap.empty()) {
339 LOG(ERROR) << "Failed to create TAP device";
340 continue;
341 }
342
343 config->set_tap_ifname(tap);
344 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900345 arc_device_ifname = arc_device_->config().tap_ifname();
Garrick Evans2961c7c2020-04-03 11:34:40 +0900346 } else {
Hugo Benichi0781d402021-02-22 13:43:11 +0900347 OneTimeContainerSetup(*datapath_, id);
Hugo Benichi33860d72020-07-09 16:34:01 +0900348 if (!datapath_->NetnsAttachName(kArcNetnsName, id)) {
349 LOG(ERROR) << "Failed to attach name " << kArcNetnsName << " to pid "
350 << id;
351 return false;
352 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900353 arc_device_ifname = ArcVethHostName(arc_device_->guest_ifname());
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900354 if (!datapath_->ConnectVethPair(id, kArcNetnsName, arc_device_ifname,
355 arc_device_->guest_ifname(),
356 arc_device_->config().mac_addr(),
357 arc_device_->config().guest_ipv4_addr(), 30,
358 arc_device_->options().fwd_multicast)) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900359 LOG(ERROR) << "Cannot create virtual link for device "
360 << arc_device_->phys_ifname();
361 return false;
362 }
Hugo Benichi40fbf0b2021-01-20 19:44:15 +0900363 // Allow netd to write to /sys/class/net/arc0/mtu (b/175571457).
Hugo Benichi0781d402021-02-22 13:43:11 +0900364 SetSysfsOwnerToAndroidRoot(id,
365 "net/" + arc_device_->guest_ifname() + "/mtu");
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900366 }
Hugo Benichif0f10c72020-07-09 10:42:45 +0900367 id_ = id;
368
369 // Create the bridge for the management device arc0.
370 // Per crbug/1008686 this device cannot be deleted and then re-added.
371 // So instead of removing the bridge when the service stops, bring down the
372 // device instead and re-up it on restart.
373 if (!datapath_->AddBridge(kArcBridge, arc_device_->config().host_ipv4_addr(),
374 30) &&
375 !datapath_->MaskInterfaceFlags(kArcBridge, IFF_UP)) {
376 LOG(ERROR) << "Failed to bring up arc bridge " << kArcBridge;
377 return false;
378 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900379
380 if (!datapath_->AddToBridge(kArcBridge, arc_device_ifname)) {
381 LOG(ERROR) << "Failed to bridge arc device " << arc_device_ifname << " to "
382 << kArcBridge;
383 return false;
384 }
Hugo Benichi33860d72020-07-09 16:34:01 +0900385 LOG(INFO) << "Started ARC management device " << *arc_device_.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900386
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900387 // Start already known Shill <-> ARC mapped devices.
Hugo Benichif0f10c72020-07-09 10:42:45 +0900388 for (const auto& ifname : shill_devices_)
389 AddDevice(ifname);
Garrick Evanscb791e72019-11-11 15:44:34 +0900390
Garrick Evansf29f5a32019-12-06 11:34:25 +0900391 return true;
Garrick Evanscb791e72019-11-11 15:44:34 +0900392}
393
Garrick Evans015b0d62020-02-07 09:06:38 +0900394void ArcService::Stop(uint32_t id) {
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900395 if (!IsStarted()) {
396 LOG(ERROR) << "ArcService was not running";
397 return;
398 }
399
400 // After the ARC container has stopped, the pid is not known anymore.
401 if (guest_ == GuestMessage::ARC_VM && id_ != id) {
402 LOG(ERROR) << "Mismatched ARCVM CIDs " << id_ << " != " << id;
403 return;
404 }
405
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900406 // Stop Shill <-> ARC mapped devices.
Hugo Benichif0f10c72020-07-09 10:42:45 +0900407 for (const auto& ifname : shill_devices_)
408 RemoveDevice(ifname);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900409
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900410 // Per crbug/1008686 this device cannot be deleted and then re-added.
411 // So instead of removing the bridge, bring it down and mark it. This will
412 // allow us to detect if the device is re-added in case of a crash restart
413 // and do the right thing.
414 if (!datapath_->MaskInterfaceFlags(kArcBridge, IFF_DEBUG, IFF_UP))
415 LOG(ERROR) << "Failed to bring down arc bridge "
416 << "- it may not restart correctly";
417
Hugo Benichi33860d72020-07-09 16:34:01 +0900418 if (guest_ == GuestMessage::ARC) {
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900419 datapath_->RemoveInterface(ArcVethHostName(arc_device_->phys_ifname()));
Hugo Benichi33860d72020-07-09 16:34:01 +0900420 if (!datapath_->NetnsDeleteName(kArcNetnsName))
421 LOG(WARNING) << "Failed to delete netns name " << kArcNetnsName;
Hugo Benichif0f10c72020-07-09 10:42:45 +0900422 }
423
424 // Destroy allocated TAP devices if any, including the ARC management device.
425 for (auto* config : all_configs_) {
426 if (config->tap_ifname().empty())
427 continue;
428 datapath_->RemoveInterface(config->tap_ifname());
429 config->set_tap_ifname("");
Hugo Benichi33860d72020-07-09 16:34:01 +0900430 }
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900431
Hugo Benichi33860d72020-07-09 16:34:01 +0900432 LOG(INFO) << "Stopped ARC management device " << *arc_device_.get();
Hugo Benichi4d4bb8f2020-07-07 12:16:07 +0900433 id_ = kInvalidId;
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900434}
435
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900436void ArcService::OnDevicesChanged(const std::set<std::string>& added,
437 const std::set<std::string>& removed) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900438 for (const std::string& ifname : removed) {
439 shill_devices_.erase(ifname);
440 RemoveDevice(ifname);
441 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900442
Hugo Benichif0f10c72020-07-09 10:42:45 +0900443 for (const std::string& ifname : added) {
444 shill_devices_.insert(ifname);
445 AddDevice(ifname);
446 }
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900447}
448
449void ArcService::AddDevice(const std::string& ifname) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900450 if (!IsStarted())
451 return;
452
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900453 if (ifname.empty())
454 return;
455
456 if (devices_.find(ifname) != devices_.end()) {
457 LOG(DFATAL) << "Attemping to add already tracked device: " << ifname;
458 return;
459 }
460
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900461 auto itype = InterfaceTypeFor(ifname);
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900462 Device::Options opts{
463 .fwd_multicast = IsMulticastInterface(ifname),
464 // TODO(crbug/726815) Also enable |ipv6_enabled| for cellular networks
Hugo Benichif0f10c72020-07-09 10:42:45 +0900465 // once IPv6 is enabled on cellular networks in Shill.
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900466 .ipv6_enabled =
467 (itype == InterfaceType::ETHERNET || itype == InterfaceType::WIFI),
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900468 .adb_allowed =
469 (itype == InterfaceType::ETHERNET || itype == InterfaceType::WIFI),
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900470 };
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900471
472 auto config = AcquireConfig(ifname);
473 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
533void ArcService::RemoveDevice(const std::string& ifname) {
Hugo Benichif0f10c72020-07-09 10:42:45 +0900534 if (!IsStarted())
535 return;
536
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900537 const auto it = devices_.find(ifname);
538 if (it == devices_.end()) {
539 LOG(WARNING) << "Unknown device: " << ifname;
Garrick Evanscb791e72019-11-11 15:44:34 +0900540 return;
541 }
542
Hugo Benichif0f10c72020-07-09 10:42:45 +0900543 const auto* device = it->second.get();
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900544 LOG(INFO) << "Removing device " << *device;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900545
Garrick Evans209a80a2020-11-30 14:42:40 +0900546 device_changed_handler_.Run(*device, Device::ChangeEvent::REMOVED, guest_);
547
Hugo Benichi4833fda2020-07-06 14:56:56 +0900548 forwarder_->StopForwarding(device->phys_ifname(), device->host_ifname(),
549 device->options().ipv6_enabled,
550 device->options().fwd_multicast);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900551
552 // ARCVM TAP devices are removed in VmImpl::Stop() when the service stops
Hugo Benichi4833fda2020-07-06 14:56:56 +0900553 if (guest_ == GuestMessage::ARC)
554 datapath_->RemoveInterface(ArcVethHostName(device->phys_ifname()));
Garrick Evans54861622019-07-19 09:05:09 +0900555
Hugo Benichi8d622b52020-08-13 15:24:12 +0900556 datapath_->StopRoutingDevice(device->phys_ifname(), device->host_ifname(),
557 device->config().guest_ipv4_addr(),
Hugo Benichi93306e52020-12-04 16:08:00 +0900558 TrafficSource::ARC, false /*route_on_vpn*/);
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900559 datapath_->RemoveBridge(device->host_ifname());
Jason Jeremy Iman3081d0e2020-03-04 15:52:06 +0900560 if (device->options().adb_allowed)
561 datapath_->DeleteAdbPortAccessRule(ifname);
Hugo Benichif0f10c72020-07-09 10:42:45 +0900562
563 ReleaseConfig(ifname, it->second->release_config());
564 devices_.erase(it);
Garrick Evanscb791e72019-11-11 15:44:34 +0900565}
566
Garrick Evans38b25a42020-04-06 15:17:42 +0900567std::vector<const Device::Config*> ArcService::GetDeviceConfigs() const {
Hugo Benichi8e448422020-07-07 10:49:00 +0900568 std::vector<const Device::Config*> configs;
569 for (auto* c : all_configs_)
570 configs.emplace_back(c);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900571
Hugo Benichi8e448422020-07-07 10:49:00 +0900572 return configs;
Garrick Evanse94b6de2020-02-20 09:19:13 +0900573}
Garrick Evans02e6e872020-11-30 11:53:13 +0900574
575void ArcService::ScanDevices(
576 base::RepeatingCallback<void(const Device&)> callback) const {
577 for (const auto& [_, d] : devices_)
578 callback.Run(*d.get());
579}
580
Garrick Evans3388a032020-03-24 11:25:55 +0900581} // namespace patchpanel