blob: cc5df20753dd4f5c8cd6930f5eb72ec802b15ad4 [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
5#include "arc/network/arc_service.h"
6
Garrick Evans54861622019-07-19 09:05:09 +09007#include <linux/rtnetlink.h>
8#include <net/if.h>
9
Garrick Evans5d55f5e2019-07-17 15:28:10 +090010#include <utility>
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090011#include <vector>
Garrick Evans5d55f5e2019-07-17 15:28:10 +090012
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>
18#include <base/strings/string_util.h>
Garrick Evans54861622019-07-19 09:05:09 +090019#include <base/strings/stringprintf.h>
Garrick Evans1f5a3612019-11-08 12:59:03 +090020#include <brillo/key_value_store.h>
Garrick Evansb4eb3892019-11-13 12:07:07 +090021#include <chromeos/constants/vm_tools.h>
Garrick Evans54861622019-07-19 09:05:09 +090022
23#include "arc/network/datapath.h"
Garrick Evans54861622019-07-19 09:05:09 +090024#include "arc/network/mac_address_generator.h"
Jason Jeremy Imanf4156cb2019-11-14 15:36:22 +090025#include "arc/network/manager.h"
Garrick Evans3915af32019-07-25 15:44:34 +090026#include "arc/network/minijailed_process_runner.h"
Garrick Evans54861622019-07-19 09:05:09 +090027#include "arc/network/net_util.h"
28#include "arc/network/scoped_ns.h"
Garrick Evans5d55f5e2019-07-17 15:28:10 +090029
30namespace arc_networkd {
Garrick Evansf29f5a32019-12-06 11:34:25 +090031namespace test {
32GuestMessage::GuestType guest = GuestMessage::UNKNOWN_GUEST;
33} // namespace test
34
Garrick Evans5d55f5e2019-07-17 15:28:10 +090035namespace {
Garrick Evans015b0d62020-02-07 09:06:38 +090036constexpr pid_t kInvalidPID = 0;
Garrick Evansb4eb3892019-11-13 12:07:07 +090037constexpr pid_t kTestPID = -2;
Garrick Evans015b0d62020-02-07 09:06:38 +090038constexpr uint32_t kInvalidCID = 0;
Garrick Evanse94b6de2020-02-20 09:19:13 +090039constexpr char kArcIfname[] = "arc0";
40constexpr char kArcBridge[] = "arcbr0";
41constexpr char kArcVmIfname[] = "arc1";
42constexpr char kArcVmBridge[] = "arc_br1";
Garrick Evans54861622019-07-19 09:05:09 +090043
Garrick Evans6d227b92019-12-03 16:11:29 +090044void OneTimeSetup(const Datapath& datapath) {
Garrick Evansa34b5862019-11-20 09:34:01 +090045 static bool done = false;
46 if (done)
47 return;
48
Garrick Evans6d227b92019-12-03 16:11:29 +090049 auto& runner = datapath.runner();
50
51 // Load networking modules needed by Android that are not compiled in the
52 // kernel. Android does not allow auto-loading of kernel modules.
Garrick Evansa34b5862019-11-20 09:34:01 +090053 // These must succeed.
Garrick Evans8e8e3472020-01-23 14:03:50 +090054 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +090055 // The netfilter modules needed by netd for iptables commands.
56 "ip6table_filter",
57 "ip6t_ipv6header",
58 "ip6t_REJECT",
59 // The xfrm modules needed for Android's ipsec APIs.
60 "xfrm4_mode_transport",
61 "xfrm4_mode_tunnel",
62 "xfrm6_mode_transport",
63 "xfrm6_mode_tunnel",
64 // The ipsec modules for AH and ESP encryption for ipv6.
65 "ah6",
66 "esp6",
67 }) != 0) {
68 LOG(ERROR) << "One or more required kernel modules failed to load."
69 << " Some Android functionality may be broken.";
70 }
71 // Optional modules.
Garrick Evans8e8e3472020-01-23 14:03:50 +090072 if (runner.modprobe_all({
Garrick Evansa34b5862019-11-20 09:34:01 +090073 // This module is not available in kernels < 3.18
74 "nf_reject_ipv6",
75 // These modules are needed for supporting Chrome traffic on Android
76 // VPN which uses Android's NAT feature. Android NAT sets up
77 // iptables
78 // rules that use these conntrack modules for FTP/TFTP.
79 "nf_nat_ftp",
80 "nf_nat_tftp",
Hugo Benichia0cde9e2019-12-16 11:57:20 +090081 // The tun module is needed by the Android 464xlat clatd process.
82 "tun",
Garrick Evansa34b5862019-11-20 09:34:01 +090083 }) != 0) {
84 LOG(WARNING) << "One or more optional kernel modules failed to load.";
85 }
86
Garrick Evans6d227b92019-12-03 16:11:29 +090087 // This is only needed for CTS (b/27932574).
Garrick Evans8e8e3472020-01-23 14:03:50 +090088 if (runner.chown("655360", "655360", "/sys/class/xt_idletimer") != 0) {
Garrick Evans6d227b92019-12-03 16:11:29 +090089 LOG(ERROR) << "Failed to change ownership of xt_idletimer.";
90 }
91
Garrick Evansa34b5862019-11-20 09:34:01 +090092 done = true;
93}
94
Garrick Evans508a4bc2019-11-14 08:45:52 +090095bool IsArcVm() {
96 const base::FilePath path("/run/chrome/is_arcvm");
97 std::string contents;
98 if (!base::ReadFileToString(path, &contents)) {
99 PLOG(ERROR) << "Could not read " << path.value();
100 }
101 return contents == "1";
102}
103
Garrick Evansf29f5a32019-12-06 11:34:25 +0900104GuestMessage::GuestType ArcGuest() {
105 if (test::guest != GuestMessage::UNKNOWN_GUEST)
106 return test::guest;
Garrick Evans508a4bc2019-11-14 08:45:52 +0900107
Garrick Evansb05a7ff2020-02-18 12:59:55 +0900108 return IsArcVm() ? GuestMessage::ARC_VM : GuestMessage::ARC;
Garrick Evans508a4bc2019-11-14 08:45:52 +0900109}
110
Garrick Evanse94b6de2020-02-20 09:19:13 +0900111// Returns the configuration for the ARC management interface used for VPN
112// forwarding, ADB-over-TCP and single-networked ARCVM.
113std::unique_ptr<Device::Config> MakeArcConfig(AddressManager* addr_mgr,
114 bool is_arcvm) {
115 const char* ifname = is_arcvm ? kArcVmBridge : kArcBridge;
116 auto ipv4_subnet = addr_mgr->AllocateIPv4Subnet(
117 is_arcvm ? AddressManager::Guest::VM_ARC : AddressManager::Guest::ARC);
118 if (!ipv4_subnet) {
119 LOG(ERROR) << "Subnet already in use or unavailable. Cannot make device: "
120 << ifname;
121 return nullptr;
122 }
123 auto host_ipv4_addr = ipv4_subnet->AllocateAtOffset(0);
124 if (!host_ipv4_addr) {
125 LOG(ERROR)
126 << "Bridge address already in use or unavailable. Cannot make device: "
127 << ifname;
128 return nullptr;
129 }
130 auto guest_ipv4_addr = ipv4_subnet->AllocateAtOffset(1);
131 if (!guest_ipv4_addr) {
132 LOG(ERROR)
133 << "ARC address already in use or unavailable. Cannot make device: "
134 << ifname;
135 return nullptr;
136 }
137
138 return std::make_unique<Device::Config>(
139 ifname, is_arcvm ? kArcVmIfname : kArcIfname,
140 addr_mgr->GenerateMacAddress(), std::move(ipv4_subnet),
141 std::move(host_ipv4_addr), std::move(guest_ipv4_addr));
142}
143
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900144} // namespace
145
Garrick Evans69b85872020-02-04 11:40:26 +0900146ArcService::ArcService(ShillClient* shill_client,
147 DeviceManagerBase* dev_mgr,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900148 Datapath* datapath,
149 AddressManager* addr_mgr,
150 TrafficForwarder* forwarder)
151 : shill_client_(shill_client),
152 dev_mgr_(dev_mgr),
153 datapath_(datapath),
154 addr_mgr_(addr_mgr),
155 forwarder_(forwarder) {
Garrick Evans69b85872020-02-04 11:40:26 +0900156 DCHECK(shill_client_);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900157 DCHECK(dev_mgr_);
Taoyu Li179dcc62019-10-17 11:21:08 +0900158 DCHECK(datapath_);
Garrick Evans3915af32019-07-25 15:44:34 +0900159
Garrick Evansf29f5a32019-12-06 11:34:25 +0900160 dev_mgr_->RegisterDeviceAddedHandler(
161 GuestMessage::ARC,
162 base::Bind(&ArcService::OnDeviceAdded, base::Unretained(this)));
163 dev_mgr_->RegisterDeviceRemovedHandler(
164 GuestMessage::ARC,
165 base::Bind(&ArcService::OnDeviceRemoved, base::Unretained(this)));
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900166
167 shill_client_->RegisterDefaultInterfaceChangedHandler(base::Bind(
168 &ArcService::OnDefaultInterfaceChanged, weak_factory_.GetWeakPtr()));
Garrick Evansf29f5a32019-12-06 11:34:25 +0900169}
170
171ArcService::~ArcService() {
Garrick Evans664a82f2019-12-17 12:18:05 +0900172 if (impl_) {
173 // Stop the service.
174 Stop(impl_->id());
175 // Delete all the bridges and veth pairs.
176 dev_mgr_->ProcessDevices(
177 base::Bind(&ArcService::OnDeviceRemoved, weak_factory_.GetWeakPtr()));
178 }
Garrick Evansf29f5a32019-12-06 11:34:25 +0900179 dev_mgr_->UnregisterAllGuestHandlers(GuestMessage::ARC);
Garrick Evans54861622019-07-19 09:05:09 +0900180}
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900181
Garrick Evans015b0d62020-02-07 09:06:38 +0900182bool ArcService::Start(uint32_t id) {
Garrick Evansf29f5a32019-12-06 11:34:25 +0900183 if (impl_) {
Garrick Evans015b0d62020-02-07 09:06:38 +0900184 uint32_t prev_id;
Garrick Evansf29f5a32019-12-06 11:34:25 +0900185 if (impl_->IsStarted(&prev_id)) {
186 LOG(WARNING) << "Already running - did something crash?"
187 << " Stopping and restarting...";
188 Stop(prev_id);
189 }
Garrick Evansa51d0a12019-11-28 13:51:23 +0900190 }
191
Garrick Evansf29f5a32019-12-06 11:34:25 +0900192 const auto guest = ArcGuest();
193 if (guest == GuestMessage::ARC_VM)
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900194 impl_ = std::make_unique<VmImpl>(shill_client_, datapath_, addr_mgr_,
195 forwarder_);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900196 else
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900197 impl_ = std::make_unique<ContainerImpl>(datapath_, addr_mgr_, forwarder_,
198 guest);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900199
200 if (!impl_->Start(id)) {
201 impl_.reset();
Garrick Evans508a4bc2019-11-14 08:45:52 +0900202 return false;
Garrick Evansf29f5a32019-12-06 11:34:25 +0900203 }
Garrick Evanscb791e72019-11-11 15:44:34 +0900204
205 // Start known host devices, any new ones will be setup in the process.
206 dev_mgr_->ProcessDevices(
207 base::Bind(&ArcService::StartDevice, weak_factory_.GetWeakPtr()));
208
Garrick Evansf29f5a32019-12-06 11:34:25 +0900209 dev_mgr_->OnGuestStart(guest);
210 return true;
Garrick Evanscb791e72019-11-11 15:44:34 +0900211}
212
Garrick Evans015b0d62020-02-07 09:06:38 +0900213void ArcService::Stop(uint32_t id) {
Garrick Evansf29f5a32019-12-06 11:34:25 +0900214 if (!impl_)
215 return;
216
217 dev_mgr_->OnGuestStop(impl_->guest());
Garrick Evans54861622019-07-19 09:05:09 +0900218
219 // Stop known host devices. Note that this does not teardown any existing
220 // devices.
221 dev_mgr_->ProcessDevices(
222 base::Bind(&ArcService::StopDevice, weak_factory_.GetWeakPtr()));
Garrick Evans21173b12019-11-20 15:23:16 +0900223
224 impl_->Stop(id);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900225 impl_.reset();
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900226}
227
Garrick Evans54861622019-07-19 09:05:09 +0900228void ArcService::OnDeviceAdded(Device* device) {
Garrick Evans54861622019-07-19 09:05:09 +0900229 const auto& config = device->config();
230
231 LOG(INFO) << "Adding device " << device->ifname()
232 << " bridge: " << config.host_ifname()
Garrick Evans310ab552019-10-08 11:07:53 +0900233 << " guest_iface: " << config.guest_ifname();
Garrick Evans54861622019-07-19 09:05:09 +0900234
235 // Create the bridge.
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900236 if (!datapath_->AddBridge(config.host_ifname(), config.host_ipv4_addr(),
237 30)) {
Garrick Evanse94b6de2020-02-20 09:19:13 +0900238 LOG(ERROR) << "Failed to setup arc bridge: " << config.host_ifname();
239 return;
Garrick Evans54861622019-07-19 09:05:09 +0900240 }
241
Garrick Evanse94b6de2020-02-20 09:19:13 +0900242 // Set up iptables.
243 if (!datapath_->AddInboundIPv4DNAT(
244 device->ifname(), IPv4AddressToString(config.guest_ipv4_addr())))
245 LOG(ERROR) << "Failed to configure ingress traffic rules for "
246 << device->ifname();
Garrick Evans54861622019-07-19 09:05:09 +0900247
Garrick Evanse94b6de2020-02-20 09:19:13 +0900248 if (!datapath_->AddOutboundIPv4(config.host_ifname()))
249 LOG(ERROR) << "Failed to configure egress traffic rules";
Garrick Evans54861622019-07-19 09:05:09 +0900250
Garrick Evansa1134d72019-12-02 14:25:37 +0900251 device->set_context(std::make_unique<Context>());
Garrick Evans54861622019-07-19 09:05:09 +0900252
253 StartDevice(device);
254}
255
256void ArcService::StartDevice(Device* device) {
Garrick Evans310ab552019-10-08 11:07:53 +0900257 // This can happen if OnDeviceAdded is invoked when the container is down.
Garrick Evansf29f5a32019-12-06 11:34:25 +0900258 if (!impl_ || !impl_->IsStarted())
Garrick Evans54861622019-07-19 09:05:09 +0900259 return;
260
Garrick Evanse94b6de2020-02-20 09:19:13 +0900261 // For now, only start devices for ARC++.
262 if (impl_->guest() != GuestMessage::ARC)
263 return;
264
Garrick Evans2c263102019-07-26 16:07:18 +0900265 // If there is no context, then this is a new device and it needs to run
266 // through the full setup process.
Garrick Evansa1134d72019-12-02 14:25:37 +0900267 Context* ctx = dynamic_cast<Context*>(device->context());
Garrick Evans2c263102019-07-26 16:07:18 +0900268 if (!ctx)
Garrick Evans54861622019-07-19 09:05:09 +0900269 return OnDeviceAdded(device);
270
Garrick Evans2c263102019-07-26 16:07:18 +0900271 if (ctx->IsStarted()) {
272 LOG(ERROR) << "Attempt to restart device " << device->ifname();
273 return;
274 }
275
Garrick Evansd90a3822019-11-12 17:53:08 +0900276 if (!impl_->OnStartDevice(device)) {
Garrick Evanscb791e72019-11-11 15:44:34 +0900277 LOG(ERROR) << "Failed to start device " << device->ifname();
278 return;
279 }
280
Garrick Evansb4eb3892019-11-13 12:07:07 +0900281 ctx->Start();
Garrick Evans54861622019-07-19 09:05:09 +0900282}
283
284void ArcService::OnDeviceRemoved(Device* device) {
Garrick Evans310ab552019-10-08 11:07:53 +0900285 // If the container is down, this call does nothing.
Garrick Evans54861622019-07-19 09:05:09 +0900286 StopDevice(device);
287
288 const auto& config = device->config();
289
290 LOG(INFO) << "Removing device " << device->ifname()
291 << " bridge: " << config.host_ifname()
292 << " guest_iface: " << config.guest_ifname();
293
Garrick Evanse94b6de2020-02-20 09:19:13 +0900294 datapath_->RemoveOutboundIPv4(config.host_ifname());
295 datapath_->RemoveInboundIPv4DNAT(
296 device->ifname(), IPv4AddressToString(config.guest_ipv4_addr()));
Garrick Evans54861622019-07-19 09:05:09 +0900297
Garrick Evanse94b6de2020-02-20 09:19:13 +0900298 datapath_->RemoveBridge(config.host_ifname());
Garrick Evans54861622019-07-19 09:05:09 +0900299
Garrick Evansa1134d72019-12-02 14:25:37 +0900300 device->set_context(nullptr);
Garrick Evans54861622019-07-19 09:05:09 +0900301}
302
303void ArcService::StopDevice(Device* device) {
Garrick Evans310ab552019-10-08 11:07:53 +0900304 // This can happen if the device if OnDeviceRemoved is invoked when the
305 // container is down.
Garrick Evansf29f5a32019-12-06 11:34:25 +0900306 if (!impl_ || !impl_->IsStarted())
Garrick Evans54861622019-07-19 09:05:09 +0900307 return;
308
Garrick Evanse94b6de2020-02-20 09:19:13 +0900309 // For now, devices are only started for ARC++.
310 if (impl_->guest() != GuestMessage::ARC)
311 return;
312
Garrick Evansa1134d72019-12-02 14:25:37 +0900313 Context* ctx = dynamic_cast<Context*>(device->context());
Garrick Evans2c263102019-07-26 16:07:18 +0900314 if (!ctx) {
315 LOG(ERROR) << "Attempt to stop removed device " << device->ifname();
316 return;
317 }
318
319 if (!ctx->IsStarted()) {
320 LOG(ERROR) << "Attempt to re-stop device " << device->ifname();
321 return;
322 }
323
Garrick Evansd90a3822019-11-12 17:53:08 +0900324 impl_->OnStopDevice(device);
Garrick Evanscb791e72019-11-11 15:44:34 +0900325
326 ctx->Stop();
327}
328
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900329void ArcService::OnDefaultInterfaceChanged(const std::string& new_ifname,
330 const std::string& prev_ifname) {
Garrick Evansf29f5a32019-12-06 11:34:25 +0900331 if (impl_)
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900332 impl_->OnDefaultInterfaceChanged(new_ifname, prev_ifname);
Garrick Evans54861622019-07-19 09:05:09 +0900333}
Garrick Evansba575742019-07-17 15:48:08 +0900334
Garrick Evanse94b6de2020-02-20 09:19:13 +0900335Device* ArcService::ArcDevice() const {
336 if (!impl_)
337 return nullptr;
338
339 return impl_->ArcDevice();
340}
341
Garrick Evans2c263102019-07-26 16:07:18 +0900342// Context
343
344ArcService::Context::Context() : Device::Context() {
345 Stop();
346}
347
348void ArcService::Context::Start() {
349 Stop();
350 started_ = true;
351}
352
353void ArcService::Context::Stop() {
354 started_ = false;
Garrick Evans2c263102019-07-26 16:07:18 +0900355}
356
357bool ArcService::Context::IsStarted() const {
358 return started_;
359}
360
Garrick Evansb4eb3892019-11-13 12:07:07 +0900361const std::string& ArcService::Context::TAP() const {
362 return tap_;
363}
364
365void ArcService::Context::SetTAP(const std::string& tap) {
366 tap_ = tap;
367}
368
Garrick Evansd90a3822019-11-12 17:53:08 +0900369// ARC++ specific functions.
370
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900371ArcService::ContainerImpl::ContainerImpl(Datapath* datapath,
372 AddressManager* addr_mgr,
373 TrafficForwarder* forwarder,
Garrick Evansd90a3822019-11-12 17:53:08 +0900374 GuestMessage::GuestType guest)
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900375 : pid_(kInvalidPID),
376 datapath_(datapath),
377 addr_mgr_(addr_mgr),
378 forwarder_(forwarder),
379 guest_(guest) {
Garrick Evans6d227b92019-12-03 16:11:29 +0900380 OneTimeSetup(*datapath_);
Garrick Evansa34b5862019-11-20 09:34:01 +0900381}
Garrick Evansd90a3822019-11-12 17:53:08 +0900382
Garrick Evansb4eb3892019-11-13 12:07:07 +0900383GuestMessage::GuestType ArcService::ContainerImpl::guest() const {
384 return guest_;
385}
386
Garrick Evans015b0d62020-02-07 09:06:38 +0900387uint32_t ArcService::ContainerImpl::id() const {
Garrick Evans664a82f2019-12-17 12:18:05 +0900388 return pid_;
389}
390
Garrick Evans015b0d62020-02-07 09:06:38 +0900391bool ArcService::ContainerImpl::Start(uint32_t pid) {
Garrick Evansa51d0a12019-11-28 13:51:23 +0900392 // This could happen if something crashes and the stop signal is not sent.
393 // It can probably be addressed by stopping and restarting the service.
394 if (pid_ != kInvalidPID)
395 return false;
396
Garrick Evans4dec0c42019-11-29 12:51:57 +0900397 if (pid == kInvalidPID) {
Garrick Evansd90a3822019-11-12 17:53:08 +0900398 LOG(ERROR) << "Cannot start service - invalid container PID";
399 return false;
400 }
Garrick Evans4dec0c42019-11-29 12:51:57 +0900401 pid_ = pid;
Garrick Evansd90a3822019-11-12 17:53:08 +0900402
Garrick Evanse94b6de2020-02-20 09:19:13 +0900403 Device::Options opts{
404 .fwd_multicast = false,
405 .ipv6_enabled = false,
406 .use_default_interface = false,
407 .is_android = true,
408 .is_sticky = true,
409 };
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900410 auto config = MakeArcConfig(addr_mgr_, false /*is_arcvm*/);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900411
412 // Create the bridge.
413 // Per crbug/1008686 this device cannot be deleted and then re-added.
414 // So instead of removing the bridge when the service stops, bring down the
415 // device instead and re-up it on restart.
416 if (!datapath_->AddBridge(kArcBridge, config->host_ipv4_addr(), 30) &&
417 !datapath_->MaskInterfaceFlags(kArcBridge, IFF_UP)) {
418 LOG(ERROR) << "Failed to bring up arc bridge: " << kArcBridge;
419 return false;
420 }
421
422 arc_device_ = std::make_unique<Device>(kArcIfname, std::move(config), opts,
423 GuestMessage::ARC);
424
425 OnStartDevice(arc_device_.get());
426
Garrick Evansd90a3822019-11-12 17:53:08 +0900427 LOG(INFO) << "ARC++ network service started {pid: " << pid_ << "}";
428 return true;
429}
430
Garrick Evans015b0d62020-02-07 09:06:38 +0900431void ArcService::ContainerImpl::Stop(uint32_t /*pid*/) {
Garrick Evans4dec0c42019-11-29 12:51:57 +0900432 if (!IsStarted())
Taoyu Li1c96d272019-12-13 14:17:43 +0900433 return;
Garrick Evans4dec0c42019-11-29 12:51:57 +0900434
Garrick Evanse94b6de2020-02-20 09:19:13 +0900435 // Per crbug/1008686 this device cannot be deleted and then re-added.
436 // So instead of removing the bridge, bring it down and mark it. This will
437 // allow us to detect if the device is re-added in case of a crash restart
438 // and do the right thing.
439 if (arc_device_) {
440 OnStopDevice(arc_device_.get());
441 if (!datapath_->MaskInterfaceFlags(kArcBridge, IFF_DEBUG, IFF_UP))
442 LOG(ERROR) << "Failed to bring down arc bridge "
443 << "- it may not restart correctly";
444 }
Garrick Evansd90a3822019-11-12 17:53:08 +0900445
446 LOG(INFO) << "ARC++ network service stopped {pid: " << pid_ << "}";
447 pid_ = kInvalidPID;
448}
449
Garrick Evans015b0d62020-02-07 09:06:38 +0900450bool ArcService::ContainerImpl::IsStarted(uint32_t* pid) const {
Garrick Evansa51d0a12019-11-28 13:51:23 +0900451 if (pid)
452 *pid = pid_;
453
Garrick Evansd90a3822019-11-12 17:53:08 +0900454 return pid_ != kInvalidPID;
455}
456
457bool ArcService::ContainerImpl::OnStartDevice(Device* device) {
458 const auto& config = device->config();
459
460 LOG(INFO) << "Starting device " << device->ifname()
461 << " bridge: " << config.host_ifname()
Garrick Evansb4eb3892019-11-13 12:07:07 +0900462 << " guest_iface: " << config.guest_ifname() << " pid: " << pid_;
Garrick Evansd90a3822019-11-12 17:53:08 +0900463
Garrick Evans2470caa2020-03-04 14:15:41 +0900464 // Set up the virtual pair inside the container namespace.
465 const std::string veth_ifname = ArcVethHostName(config.guest_ifname());
466 {
467 ScopedNS ns(pid_);
468 if (!ns.IsValid() && pid_ != kTestPID) {
469 LOG(ERROR)
470 << "Cannot create virtual link -- invalid container namespace?";
471 return false;
472 }
473
474 if (!datapath_->AddVirtualInterfacePair(veth_ifname,
475 config.guest_ifname())) {
476 LOG(ERROR) << "Failed to create virtual interface pair for "
477 << device->ifname();
478 return false;
479 }
480
481 if (!datapath_->ConfigureInterface(
482 config.guest_ifname(), config.guest_mac_addr(),
483 config.guest_ipv4_addr(), 30, true /* link up */,
484 device->options().fwd_multicast)) {
485 LOG(ERROR) << "Failed to configure interface " << config.guest_ifname();
486 datapath_->RemoveInterface(config.guest_ifname());
487 return false;
488 }
Garrick Evansd90a3822019-11-12 17:53:08 +0900489 }
490
Garrick Evans2470caa2020-03-04 14:15:41 +0900491 // Now pull the host end out into the root namespace and add it to the bridge.
492 if (datapath_->runner().RestoreDefaultNamespace(veth_ifname, pid_) != 0) {
493 LOG(ERROR) << "Failed to prepare interface " << veth_ifname;
494 {
495 ScopedNS ns(pid_);
496 if (ns.IsValid()) {
497 datapath_->RemoveInterface(config.guest_ifname());
498 } else {
499 LOG(ERROR) << "Failed to re-enter container namespace."
500 << " Subsequent attempts to restart " << device->ifname()
501 << " may not succeed.";
502 }
503 }
504 return false;
505 }
506 if (!datapath_->ToggleInterface(veth_ifname, true /*up*/)) {
507 LOG(ERROR) << "Failed to bring up interface " << veth_ifname;
Garrick Evansd90a3822019-11-12 17:53:08 +0900508 datapath_->RemoveInterface(veth_ifname);
Garrick Evansd90a3822019-11-12 17:53:08 +0900509 return false;
510 }
Garrick Evans2470caa2020-03-04 14:15:41 +0900511 if (!datapath_->AddToBridge(config.host_ifname(), veth_ifname)) {
512 datapath_->RemoveInterface(veth_ifname);
513 LOG(ERROR) << "Failed to bridge interface " << veth_ifname;
514 return false;
515 }
Garrick Evansd90a3822019-11-12 17:53:08 +0900516
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900517 if (device != arc_device_.get())
518 forwarder_->StartForwarding(
519 device->ifname(), device->config().host_ifname(),
520 device->config().guest_ipv4_addr(), device->options().ipv6_enabled,
521 device->options().fwd_multicast);
522
Garrick Evansd90a3822019-11-12 17:53:08 +0900523 return true;
524}
525
526void ArcService::ContainerImpl::OnStopDevice(Device* device) {
527 const auto& config = device->config();
528
529 LOG(INFO) << "Stopping device " << device->ifname()
530 << " bridge: " << config.host_ifname()
Garrick Evansb4eb3892019-11-13 12:07:07 +0900531 << " guest_iface: " << config.guest_ifname() << " pid: " << pid_;
Garrick Evansd90a3822019-11-12 17:53:08 +0900532
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900533 if (device != arc_device_.get())
534 forwarder_->StopForwarding(device->ifname(), device->config().host_ifname(),
535 device->options().ipv6_enabled,
536 device->options().fwd_multicast);
537
Garrick Evanse94b6de2020-02-20 09:19:13 +0900538 datapath_->RemoveInterface(ArcVethHostName(device->ifname()));
Garrick Evansd90a3822019-11-12 17:53:08 +0900539}
540
541void ArcService::ContainerImpl::OnDefaultInterfaceChanged(
Garrick Evansb05a7ff2020-02-18 12:59:55 +0900542 const std::string& new_ifname, const std::string& prev_ifname) {}
Garrick Evansd90a3822019-11-12 17:53:08 +0900543
Garrick Evansb4eb3892019-11-13 12:07:07 +0900544// VM specific functions
545
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900546ArcService::VmImpl::VmImpl(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900547 Datapath* datapath,
548 AddressManager* addr_mgr,
549 TrafficForwarder* forwarder)
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900550 : cid_(kInvalidCID),
551 shill_client_(shill_client),
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900552 datapath_(datapath),
553 addr_mgr_(addr_mgr),
554 forwarder_(forwarder) {}
Garrick Evansb4eb3892019-11-13 12:07:07 +0900555
556GuestMessage::GuestType ArcService::VmImpl::guest() const {
557 return GuestMessage::ARC_VM;
558}
559
Garrick Evans015b0d62020-02-07 09:06:38 +0900560uint32_t ArcService::VmImpl::id() const {
Garrick Evans664a82f2019-12-17 12:18:05 +0900561 return cid_;
562}
563
Garrick Evans015b0d62020-02-07 09:06:38 +0900564bool ArcService::VmImpl::Start(uint32_t cid) {
Garrick Evansa51d0a12019-11-28 13:51:23 +0900565 // This can happen if concierge crashes and doesn't send the vm down RPC.
566 // It can probably be addressed by stopping and restarting the service.
567 if (cid_ != kInvalidCID)
568 return false;
569
Garrick Evans015b0d62020-02-07 09:06:38 +0900570 if (cid == kInvalidCID) {
Garrick Evansb4eb3892019-11-13 12:07:07 +0900571 LOG(ERROR) << "Invalid VM cid " << cid;
572 return false;
573 }
Garrick Evansb4eb3892019-11-13 12:07:07 +0900574 cid_ = cid;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900575
Garrick Evanse94b6de2020-02-20 09:19:13 +0900576 Device::Options opts{
577 .fwd_multicast = true,
578 .ipv6_enabled = true,
579 .use_default_interface = true,
580 .is_android = true,
581 .is_sticky = true,
582 };
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900583 auto config = MakeArcConfig(addr_mgr_, true /*is_arcvm*/);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900584
585 // Create the bridge.
586 if (!datapath_->AddBridge(kArcVmBridge, config->host_ipv4_addr(), 30)) {
587 LOG(ERROR) << "Failed to setup arc bridge: " << kArcVmBridge;
588 return false;
589 }
590
591 // Setup the iptables.
592 if (!datapath_->AddLegacyIPv4DNAT(
593 IPv4AddressToString(config->guest_ipv4_addr())))
594 LOG(ERROR) << "Failed to configure ARC traffic rules";
595
596 if (!datapath_->AddOutboundIPv4(kArcVmBridge))
597 LOG(ERROR) << "Failed to configure egress traffic rules";
598
599 arc_device_ = std::make_unique<Device>(kArcVmIfname, std::move(config), opts,
600 GuestMessage::ARC_VM);
601 arc_device_->set_context(std::make_unique<Context>());
602
603 OnStartDevice(arc_device_.get());
604
605 LOG(INFO) << "ARCVM network service started {cid: " << cid_ << "}";
Garrick Evansb4eb3892019-11-13 12:07:07 +0900606 return true;
607}
608
Garrick Evans015b0d62020-02-07 09:06:38 +0900609void ArcService::VmImpl::Stop(uint32_t cid) {
Garrick Evans21173b12019-11-20 15:23:16 +0900610 if (cid_ != cid) {
611 LOG(ERROR) << "Mismatched ARCVM CIDs " << cid_ << " != " << cid;
612 return;
613 }
614
Garrick Evanse94b6de2020-02-20 09:19:13 +0900615 datapath_->RemoveOutboundIPv4(kArcVmBridge);
616 datapath_->RemoveLegacyIPv4DNAT();
617 OnStopDevice(arc_device_.get());
618 datapath_->RemoveBridge(kArcVmBridge);
619 arc_device_.reset();
620
Garrick Evansb4eb3892019-11-13 12:07:07 +0900621 LOG(INFO) << "ARCVM network service stopped {cid: " << cid_ << "}";
622 cid_ = kInvalidCID;
623}
624
Garrick Evans015b0d62020-02-07 09:06:38 +0900625bool ArcService::VmImpl::IsStarted(uint32_t* cid) const {
Garrick Evansa51d0a12019-11-28 13:51:23 +0900626 if (cid)
627 *cid = cid_;
628
Garrick Evans015b0d62020-02-07 09:06:38 +0900629 return cid_ != kInvalidCID;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900630}
631
632bool ArcService::VmImpl::OnStartDevice(Device* device) {
633 // TODO(garrick): Remove this once ARCVM supports ad hoc interface
Garrick Evans8ff08452019-11-25 09:24:26 +0900634 // configurations.
635 if (!device->UsesDefaultInterface())
Garrick Evansb4eb3892019-11-13 12:07:07 +0900636 return false;
637
638 const auto& config = device->config();
639
640 LOG(INFO) << "Starting device " << device->ifname()
641 << " bridge: " << config.host_ifname()
642 << " guest_iface: " << config.guest_ifname() << " cid: " << cid_;
643
Garrick Evansa1134d72019-12-02 14:25:37 +0900644 Context* ctx = dynamic_cast<Context*>(device->context());
Garrick Evansb4eb3892019-11-13 12:07:07 +0900645 if (!ctx) {
646 LOG(ERROR) << "Context missing";
647 return false;
648 }
649
650 // Since the interface will be added to the bridge, no address configuration
651 // should be provided here.
652 std::string tap =
653 datapath_->AddTAP("" /* auto-generate name */, nullptr /* no mac addr */,
654 nullptr /* no ipv4 subnet */, vm_tools::kCrosVmUser);
655 if (tap.empty()) {
656 LOG(ERROR) << "Failed to create TAP device for VM";
657 return false;
658 }
659
660 if (!datapath_->AddToBridge(config.host_ifname(), tap)) {
661 LOG(ERROR) << "Failed to bridge TAP device " << tap;
662 datapath_->RemoveInterface(tap);
663 return false;
664 }
665
666 ctx->SetTAP(tap);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900667 ctx->Start();
Garrick Evansb4eb3892019-11-13 12:07:07 +0900668 // TODO(garrick): Remove this once ARCVM supports ad hoc interface
669 // configurations; but for now ARCVM needs to be treated like ARC++ N.
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900670 OnDefaultInterfaceChanged(shill_client_->default_interface(),
671 "" /*previous*/);
Garrick Evansb4eb3892019-11-13 12:07:07 +0900672 return true;
673}
674
675void ArcService::VmImpl::OnStopDevice(Device* device) {
676 // TODO(garrick): Remove this once ARCVM supports ad hoc interface
Garrick Evans8ff08452019-11-25 09:24:26 +0900677 // configurations.
678 if (!device->UsesDefaultInterface())
Garrick Evansb4eb3892019-11-13 12:07:07 +0900679 return;
680
681 const auto& config = device->config();
682
683 LOG(INFO) << "Stopping " << device->ifname()
684 << " bridge: " << config.host_ifname()
685 << " guest_iface: " << config.guest_ifname() << " cid: " << cid_;
686
Garrick Evansa1134d72019-12-02 14:25:37 +0900687 Context* ctx = dynamic_cast<Context*>(device->context());
Garrick Evansb4eb3892019-11-13 12:07:07 +0900688 if (!ctx) {
689 LOG(ERROR) << "Context missing";
690 return;
691 }
692
Garrick Evanse94b6de2020-02-20 09:19:13 +0900693 // TODO(garrick): Remove this once ARCVM supports ad hoc interface
694 // configurations; but for now ARCVM needs to be treated like ARC++ N.
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900695 OnDefaultInterfaceChanged("" /*new_ifname*/,
696 shill_client_->default_interface());
Garrick Evansb4eb3892019-11-13 12:07:07 +0900697 datapath_->RemoveInterface(ctx->TAP());
Garrick Evanse94b6de2020-02-20 09:19:13 +0900698 ctx->Stop();
Garrick Evansb4eb3892019-11-13 12:07:07 +0900699}
700
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900701void ArcService::VmImpl::OnDefaultInterfaceChanged(
702 const std::string& new_ifname, const std::string& prev_ifname) {
Garrick Evansb4eb3892019-11-13 12:07:07 +0900703 if (!IsStarted())
704 return;
705
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900706 forwarder_->StopForwarding(prev_ifname, kArcVmBridge, true /*ipv6*/,
707 true /*multicast*/);
708
Garrick Evansb4eb3892019-11-13 12:07:07 +0900709 // TODO(garrick): Remove this once ARCVM supports ad hoc interface
710 // configurations; but for now ARCVM needs to be treated like ARC++ N.
711 datapath_->RemoveLegacyIPv4InboundDNAT();
Garrick Evansb4eb3892019-11-13 12:07:07 +0900712
713 // If a new default interface was given, then re-enable with that.
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900714 if (!new_ifname.empty()) {
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900715 forwarder_->StartForwarding(new_ifname, kArcVmBridge,
716 arc_device_->config().guest_ipv4_addr(),
717 true /*ipv6*/, true /*multicast*/);
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900718 datapath_->AddLegacyIPv4InboundDNAT(new_ifname);
Garrick Evansb4eb3892019-11-13 12:07:07 +0900719 }
720}
721
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900722} // namespace arc_networkd