blob: 9902d9460f2a853e69a3e62d2798f856439c1826 [file] [log] [blame]
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07001// Copyright 2016 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
Hidehiko Abe3a7e5132018-02-15 13:07:50 +09005#include "arc/network/manager.h"
Kevin Cernekee4e62cc12016-12-03 11:50:53 -08006
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07007#include <arpa/inet.h>
Hugo Benichi935eca92018-07-03 13:47:24 +09008#include <netinet/in.h>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -07009#include <stdint.h>
Garrick Evans54861622019-07-19 09:05:09 +090010#include <sys/prctl.h>
Garrick Evans96e03042019-05-28 14:30:52 +090011#include <sys/socket.h>
12#include <sys/un.h>
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070013
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080014#include <utility>
Garrick Evans96e03042019-05-28 14:30:52 +090015#include <vector>
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080016
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070017#include <base/bind.h>
18#include <base/logging.h>
Long Chengd4415582019-09-24 19:16:09 +000019#include <base/message_loop/message_loop.h>
Taoyu Lic85c44b2019-12-04 17:32:57 +090020#include <base/strings/string_number_conversions.h>
Garrick Evans96e03042019-05-28 14:30:52 +090021#include <base/strings/string_split.h>
Garrick Evans6f258d02019-06-28 16:32:07 +090022#include <base/strings/string_util.h>
Taoyu Li179dcc62019-10-17 11:21:08 +090023#include <base/strings/stringprintf.h>
Taoyu Lic85c44b2019-12-04 17:32:57 +090024#include <brillo/key_value_store.h>
Kevin Cernekee27bcaa62016-12-03 11:16:26 -080025#include <brillo/minijail/minijail.h>
26
Garrick Evans428e4762018-12-11 15:18:42 +090027#include "arc/network/ipc.pb.h"
28
Kevin Cernekee95d4ae92016-06-19 10:26:29 -070029namespace arc_networkd {
Garrick Evans08843932019-09-17 14:41:08 +090030namespace {
31
Taoyu Lic85c44b2019-12-04 17:32:57 +090032bool ShouldEnableNDProxy() {
33 static const char kLsbReleasePath[] = "/etc/lsb-release";
34 static int kMinAndroidSdkVersion = 28; // P
35 static int kMinChromeMilestone = 80;
Taoyu Li6d479442019-12-09 13:02:29 +090036 static std::array<std::string, 3> kSupportedBoards = {"atlas", "eve",
37 "eve-arcvm"};
Taoyu Lic85c44b2019-12-04 17:32:57 +090038
39 brillo::KeyValueStore store;
40 if (!store.Load(base::FilePath(kLsbReleasePath))) {
41 LOG(ERROR) << "Could not read lsb-release";
42 return false;
43 }
44
45 std::string value;
46 if (!store.GetString("CHROMEOS_ARC_ANDROID_SDK_VERSION", &value)) {
47 LOG(ERROR) << "NDProxy disabled - cannot determine Android SDK version";
48 return false;
49 }
50 int ver = 0;
51 if (!base::StringToInt(value.c_str(), &ver)) {
52 LOG(ERROR) << "NDProxy disabled - invalid Android SDK version";
53 return false;
54 }
55 if (ver < kMinAndroidSdkVersion) {
56 LOG(INFO) << "NDProxy disabled for Android SDK " << value;
57 return false;
58 }
59
60 if (!store.GetString("CHROMEOS_RELEASE_CHROME_MILESTONE", &value)) {
61 LOG(ERROR) << "NDProxy disabled - cannot determine ChromeOS milestone";
62 return false;
63 }
64 if (!base::StringToInt(value.c_str(), &ver)) {
65 LOG(ERROR) << "NDProxy disabled - invalid ChromeOS milestone";
66 return false;
67 }
68 if (ver < kMinChromeMilestone) {
69 LOG(INFO) << "NDProxy disabled for ChromeOS milestone " << value;
70 return false;
71 }
72
73 if (!store.GetString("CHROMEOS_RELEASE_BOARD", &value)) {
74 LOG(ERROR) << "NDProxy disabled - cannot determine board";
75 return false;
76 }
77 if (std::find(kSupportedBoards.begin(), kSupportedBoards.end(), value) ==
78 kSupportedBoards.end()) {
79 LOG(INFO) << "NDProxy disabled for board " << value;
80 return false;
81 }
82 LOG(INFO) << "NDProxy enabled";
83 return true;
84}
85
Garrick Evans08843932019-09-17 14:41:08 +090086// Passes |method_call| to |handler| and passes the response to
87// |response_sender|. If |handler| returns nullptr, an empty response is
88// created and sent.
89void HandleSynchronousDBusMethodCall(
90 base::Callback<std::unique_ptr<dbus::Response>(dbus::MethodCall*)> handler,
91 dbus::MethodCall* method_call,
92 dbus::ExportedObject::ResponseSender response_sender) {
93 std::unique_ptr<dbus::Response> response = handler.Run(method_call);
94 if (!response)
95 response = dbus::Response::FromMethodCall(method_call);
96 response_sender.Run(std::move(response));
97}
98
99} // namespace
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700100
Taoyu Lice7caa62019-10-01 15:43:33 +0900101Manager::Manager(std::unique_ptr<HelperProcess> adb_proxy,
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +0900102 std::unique_ptr<HelperProcess> mcast_proxy,
Garrick Evans1f5a3612019-11-08 12:59:03 +0900103 std::unique_ptr<HelperProcess> nd_proxy)
Garrick Evans3915af32019-07-25 15:44:34 +0900104 : adb_proxy_(std::move(adb_proxy)),
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +0900105 mcast_proxy_(std::move(mcast_proxy)),
Taoyu Lice7caa62019-10-01 15:43:33 +0900106 nd_proxy_(std::move(nd_proxy)),
Garrick Evans96e03042019-05-28 14:30:52 +0900107 addr_mgr_({
Garrick Evansf4a93292019-03-13 14:19:43 +0900108 AddressManager::Guest::ARC,
109 AddressManager::Guest::ARC_NET,
Garrick Evans47c19272019-11-21 10:58:21 +0900110 AddressManager::Guest::CONTAINER,
Garrick Evans508a4bc2019-11-14 08:45:52 +0900111 AddressManager::Guest::VM_ARC,
Garrick Evans47c19272019-11-21 10:58:21 +0900112 AddressManager::Guest::VM_TERMINA,
Garrick Evansf7acc772019-10-21 15:26:15 +0900113 }) {
Taoyu Li179dcc62019-10-17 11:21:08 +0900114 runner_ = std::make_unique<MinijailedProcessRunner>();
115 datapath_ = std::make_unique<Datapath>(runner_.get());
116}
Long Chengd4415582019-09-24 19:16:09 +0000117
Garrick Evans207e7482019-12-16 11:54:36 +0900118Manager::~Manager() {
119 OnShutdown(nullptr);
120}
121
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700122int Manager::OnInit() {
Garrick Evans54861622019-07-19 09:05:09 +0900123 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800124
125 // Handle subprocess lifecycle.
126 process_reaper_.Register(this);
Hugo Benichi935eca92018-07-03 13:47:24 +0900127
128 CHECK(process_reaper_.WatchForChild(
Garrick Evans96e03042019-05-28 14:30:52 +0900129 FROM_HERE, adb_proxy_->pid(),
130 base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(),
131 adb_proxy_->pid())))
132 << "Failed to watch adb-proxy child process";
Taoyu Liaf944c92019-10-01 12:22:31 +0900133 CHECK(process_reaper_.WatchForChild(
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +0900134 FROM_HERE, mcast_proxy_->pid(),
135 base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(),
136 nd_proxy_->pid())))
137 << "Failed to watch multicast-proxy child process";
138 CHECK(process_reaper_.WatchForChild(
Taoyu Liaf944c92019-10-01 12:22:31 +0900139 FROM_HERE, nd_proxy_->pid(),
140 base::Bind(&Manager::OnSubprocessExited, weak_factory_.GetWeakPtr(),
141 nd_proxy_->pid())))
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +0900142 << "Failed to watch nd-proxy child process";
Garrick Evans96e03042019-05-28 14:30:52 +0900143
Garrick Evans49879532018-12-03 13:15:36 +0900144 // Run after Daemon::OnInit().
Eric Caruso9ce54182018-01-04 11:19:47 -0800145 base::MessageLoopForIO::current()->task_runner()->PostTask(
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700146 FROM_HERE,
147 base::Bind(&Manager::InitialSetup, weak_factory_.GetWeakPtr()));
148
149 return DBusDaemon::OnInit();
150}
151
152void Manager::InitialSetup() {
Garrick Evans08843932019-09-17 14:41:08 +0900153 LOG(INFO) << "Setting up DBus service interface";
154 dbus_svc_path_ = bus_->GetExportedObject(
155 dbus::ObjectPath(patchpanel::kPatchPanelServicePath));
156 if (!dbus_svc_path_) {
157 LOG(FATAL) << "Failed to export " << patchpanel::kPatchPanelServicePath
158 << " object";
159 }
160
161 using ServiceMethod =
162 std::unique_ptr<dbus::Response> (Manager::*)(dbus::MethodCall*);
163 const std::map<const char*, ServiceMethod> kServiceMethods = {
164 {patchpanel::kArcStartupMethod, &Manager::OnArcStartup},
165 {patchpanel::kArcShutdownMethod, &Manager::OnArcShutdown},
166 {patchpanel::kArcVmStartupMethod, &Manager::OnArcVmStartup},
167 {patchpanel::kArcVmShutdownMethod, &Manager::OnArcVmShutdown},
Garrick Evans47c19272019-11-21 10:58:21 +0900168 {patchpanel::kTerminaVmStartupMethod, &Manager::OnTerminaVmStartup},
169 {patchpanel::kTerminaVmShutdownMethod, &Manager::OnTerminaVmShutdown},
Garrick Evans08843932019-09-17 14:41:08 +0900170 };
171
172 for (const auto& kv : kServiceMethods) {
173 if (!dbus_svc_path_->ExportMethodAndBlock(
174 patchpanel::kPatchPanelInterface, kv.first,
175 base::Bind(&HandleSynchronousDBusMethodCall,
176 base::Bind(kv.second, base::Unretained(this))))) {
177 LOG(FATAL) << "Failed to export method " << kv.first;
178 }
179 }
180
181 if (!bus_->RequestOwnershipAndBlock(patchpanel::kPatchPanelServiceName,
182 dbus::Bus::REQUIRE_PRIMARY)) {
183 LOG(FATAL) << "Failed to take ownership of "
184 << patchpanel::kPatchPanelServiceName;
185 }
186 LOG(INFO) << "DBus service interface ready";
187
Taoyu Li6d479442019-12-09 13:02:29 +0900188 auto& runner = datapath_->runner();
Garrick Evans28d194e2019-12-17 10:22:28 +0900189 // Limit local port range: Android owns 47104-61000.
190 // TODO(garrick): The original history behind this tweak is gone. Some
191 // investigation is needed to see if it is still applicable.
192 if (runner.SysctlWrite("net.ipv4.ip_local_port_range", "32768 47103") != 0) {
193 LOG(ERROR) << "Failed to limit local port range. Some Android features or"
194 << " apps may not work correctly.";
195 }
Taoyu Li6d479442019-12-09 13:02:29 +0900196 // Enable IPv6 packet forarding
197 if (runner.SysctlWrite("net.ipv6.conf.all.forwarding", "1") != 0) {
198 LOG(ERROR) << "Failed to update net.ipv6.conf.all.forwarding."
199 << " IPv6 functionality may be broken.";
200 }
201 // Kernel proxy_ndp is only needed for legacy IPv6 configuration
202 if (!ShouldEnableNDProxy() &&
203 runner.SysctlWrite("net.ipv6.conf.all.proxy_ndp", "1") != 0) {
204 LOG(ERROR) << "Failed to update net.ipv6.conf.all.proxy_ndp."
205 << " IPv6 functionality may be broken.";
206 }
207
Garrick Evans428e4762018-12-11 15:18:42 +0900208 device_mgr_ = std::make_unique<DeviceManager>(
Garrick Evans08843932019-09-17 14:41:08 +0900209 std::make_unique<ShillClient>(bus_), &addr_mgr_, datapath_.get(),
Taoyu Lic85c44b2019-12-04 17:32:57 +0900210 mcast_proxy_.get(), ShouldEnableNDProxy() ? nd_proxy_.get() : nullptr);
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900211
Garrick Evans1f5a3612019-11-08 12:59:03 +0900212 arc_svc_ = std::make_unique<ArcService>(device_mgr_.get(), datapath_.get());
Garrick Evans47c19272019-11-21 10:58:21 +0900213 cros_svc_ =
214 std::make_unique<CrostiniService>(device_mgr_.get(), datapath_.get());
Taoyu Liaf944c92019-10-01 12:22:31 +0900215
216 nd_proxy_->Listen();
Long Chengd4415582019-09-24 19:16:09 +0000217}
Garrick Evans49879532018-12-03 13:15:36 +0900218
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800219void Manager::OnShutdown(int* exit_code) {
Garrick Evans207e7482019-12-16 11:54:36 +0900220 cros_svc_.reset();
221 arc_svc_.reset();
Garrick Evans428e4762018-12-11 15:18:42 +0900222 device_mgr_.reset();
Garrick Evans28d194e2019-12-17 10:22:28 +0900223
224 // Restore original local port range.
225 // TODO(garrick): The original history behind this tweak is gone. Some
226 // investigation is needed to see if it is still applicable.
227 if (datapath_->runner().SysctlWrite("net.ipv4.ip_local_port_range",
228 "32768 61000") != 0) {
229 LOG(ERROR) << "Failed to restore local port range";
230 }
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800231}
232
233void Manager::OnSubprocessExited(pid_t pid, const siginfo_t& info) {
Hugo Benichi10a2af42018-08-27 10:09:42 +0900234 LOG(ERROR) << "Subprocess " << pid << " exited unexpectedly";
235 Quit();
Kevin Cernekee27bcaa62016-12-03 11:16:26 -0800236}
237
Garrick Evanse94a14e2019-11-11 10:32:13 +0900238bool Manager::StartArc(pid_t pid) {
Garrick Evans508a4bc2019-11-14 08:45:52 +0900239 if (!arc_svc_->Start(pid))
240 return false;
Garrick Evanse94a14e2019-11-11 10:32:13 +0900241
242 GuestMessage msg;
243 msg.set_event(GuestMessage::START);
244 msg.set_type(GuestMessage::ARC);
245 msg.set_arc_pid(pid);
246 SendGuestMessage(msg);
247
248 return true;
249}
250
Garrick Evans21173b12019-11-20 15:23:16 +0900251void Manager::StopArc(pid_t pid) {
Garrick Evanse94a14e2019-11-11 10:32:13 +0900252 GuestMessage msg;
253 msg.set_event(GuestMessage::STOP);
254 msg.set_type(GuestMessage::ARC);
255 SendGuestMessage(msg);
256
Garrick Evans21173b12019-11-20 15:23:16 +0900257 arc_svc_->Stop(pid);
Garrick Evanse94a14e2019-11-11 10:32:13 +0900258}
259
Garrick Evans21173b12019-11-20 15:23:16 +0900260bool Manager::StartArcVm(int32_t cid) {
Garrick Evans508a4bc2019-11-14 08:45:52 +0900261 if (!arc_svc_->Start(cid))
262 return false;
Garrick Evanse94a14e2019-11-11 10:32:13 +0900263
264 GuestMessage msg;
265 msg.set_event(GuestMessage::START);
266 msg.set_type(GuestMessage::ARC_VM);
267 msg.set_arcvm_vsock_cid(cid);
268 SendGuestMessage(msg);
269
270 return true;
271}
272
Garrick Evans21173b12019-11-20 15:23:16 +0900273void Manager::StopArcVm(int32_t cid) {
Garrick Evanse94a14e2019-11-11 10:32:13 +0900274 GuestMessage msg;
275 msg.set_event(GuestMessage::STOP);
276 msg.set_type(GuestMessage::ARC_VM);
277 SendGuestMessage(msg);
278
Garrick Evans21173b12019-11-20 15:23:16 +0900279 arc_svc_->Stop(cid);
Garrick Evanse94a14e2019-11-11 10:32:13 +0900280}
281
Garrick Evans47c19272019-11-21 10:58:21 +0900282bool Manager::StartTerminaVm(int32_t cid) {
283 if (!cros_svc_->Start(cid))
284 return false;
285
286 GuestMessage msg;
287 msg.set_event(GuestMessage::START);
288 msg.set_type(GuestMessage::TERMINA_VM);
289 msg.set_arcvm_vsock_cid(cid);
290 SendGuestMessage(msg);
291
292 return true;
293}
294
295void Manager::StopTerminaVm(int32_t cid) {
296 GuestMessage msg;
297 msg.set_event(GuestMessage::STOP);
298 msg.set_type(GuestMessage::TERMINA_VM);
299 SendGuestMessage(msg);
300
301 cros_svc_->Stop(cid);
302}
303
Garrick Evans08843932019-09-17 14:41:08 +0900304std::unique_ptr<dbus::Response> Manager::OnArcStartup(
305 dbus::MethodCall* method_call) {
306 LOG(INFO) << "ARC++ starting up";
307
308 std::unique_ptr<dbus::Response> dbus_response(
309 dbus::Response::FromMethodCall(method_call));
310
311 dbus::MessageReader reader(method_call);
312 dbus::MessageWriter writer(dbus_response.get());
313
314 patchpanel::ArcStartupRequest request;
315 patchpanel::ArcStartupResponse response;
316
317 if (!reader.PopArrayOfBytesAsProto(&request)) {
318 LOG(ERROR) << "Unable to parse request";
319 writer.AppendProtoAsArrayOfBytes(response);
320 return dbus_response;
321 }
322
Garrick Evanse01bf072019-11-15 09:08:19 +0900323 if (!StartArc(request.pid()))
324 LOG(ERROR) << "Failed to start ARC++ network service";
Garrick Evanse94a14e2019-11-11 10:32:13 +0900325
Garrick Evans08843932019-09-17 14:41:08 +0900326 writer.AppendProtoAsArrayOfBytes(response);
327 return dbus_response;
328}
329
330std::unique_ptr<dbus::Response> Manager::OnArcShutdown(
331 dbus::MethodCall* method_call) {
332 LOG(INFO) << "ARC++ shutting down";
333
334 std::unique_ptr<dbus::Response> dbus_response(
335 dbus::Response::FromMethodCall(method_call));
336
337 dbus::MessageReader reader(method_call);
338 dbus::MessageWriter writer(dbus_response.get());
339
340 patchpanel::ArcShutdownRequest request;
341 patchpanel::ArcShutdownResponse response;
342
343 if (!reader.PopArrayOfBytesAsProto(&request)) {
344 LOG(ERROR) << "Unable to parse request";
345 writer.AppendProtoAsArrayOfBytes(response);
346 return dbus_response;
347 }
348
Garrick Evans21173b12019-11-20 15:23:16 +0900349 StopArc(request.pid());
Garrick Evanse94a14e2019-11-11 10:32:13 +0900350
Garrick Evans08843932019-09-17 14:41:08 +0900351 writer.AppendProtoAsArrayOfBytes(response);
352 return dbus_response;
353}
354
355std::unique_ptr<dbus::Response> Manager::OnArcVmStartup(
356 dbus::MethodCall* method_call) {
357 LOG(INFO) << "ARCVM starting up";
358
359 std::unique_ptr<dbus::Response> dbus_response(
360 dbus::Response::FromMethodCall(method_call));
361
362 dbus::MessageReader reader(method_call);
363 dbus::MessageWriter writer(dbus_response.get());
364
365 patchpanel::ArcVmStartupRequest request;
366 patchpanel::ArcVmStartupResponse response;
367
368 if (!reader.PopArrayOfBytesAsProto(&request)) {
369 LOG(ERROR) << "Unable to parse request";
370 writer.AppendProtoAsArrayOfBytes(response);
371 return dbus_response;
372 }
373
Garrick Evans47c19272019-11-21 10:58:21 +0900374 if (!StartArcVm(request.cid())) {
Garrick Evanse01bf072019-11-15 09:08:19 +0900375 LOG(ERROR) << "Failed to start ARCVM network service";
Garrick Evans47c19272019-11-21 10:58:21 +0900376 writer.AppendProtoAsArrayOfBytes(response);
377 return dbus_response;
Garrick Evanse01bf072019-11-15 09:08:19 +0900378 }
Garrick Evanse94a14e2019-11-11 10:32:13 +0900379
Garrick Evans47c19272019-11-21 10:58:21 +0900380 // Populate the response with the known devices.
381 auto build_resp = [](patchpanel::ArcVmStartupResponse* resp, Device* device) {
382 auto* ctx = dynamic_cast<ArcService::Context*>(device->context());
383 if (!ctx || ctx->TAP().empty())
384 return;
385
386 const auto& config = device->config();
387 auto* dev = resp->add_devices();
388 dev->set_ifname(ctx->TAP());
389 dev->set_ipv4_addr(config.guest_ipv4_addr());
390 };
391
392 device_mgr_->ProcessDevices(
393 base::Bind(build_resp, base::Unretained(&response)));
394
Garrick Evans08843932019-09-17 14:41:08 +0900395 writer.AppendProtoAsArrayOfBytes(response);
396 return dbus_response;
397}
398
399std::unique_ptr<dbus::Response> Manager::OnArcVmShutdown(
400 dbus::MethodCall* method_call) {
401 LOG(INFO) << "ARCVM shutting down";
402
403 std::unique_ptr<dbus::Response> dbus_response(
404 dbus::Response::FromMethodCall(method_call));
405
406 dbus::MessageReader reader(method_call);
407 dbus::MessageWriter writer(dbus_response.get());
408
409 patchpanel::ArcVmShutdownRequest request;
410 patchpanel::ArcVmShutdownResponse response;
411
412 if (!reader.PopArrayOfBytesAsProto(&request)) {
413 LOG(ERROR) << "Unable to parse request";
414 writer.AppendProtoAsArrayOfBytes(response);
415 return dbus_response;
416 }
417
Garrick Evans21173b12019-11-20 15:23:16 +0900418 StopArcVm(request.cid());
Garrick Evanse94a14e2019-11-11 10:32:13 +0900419
Garrick Evans08843932019-09-17 14:41:08 +0900420 writer.AppendProtoAsArrayOfBytes(response);
421 return dbus_response;
422}
423
Garrick Evans47c19272019-11-21 10:58:21 +0900424std::unique_ptr<dbus::Response> Manager::OnTerminaVmStartup(
425 dbus::MethodCall* method_call) {
426 LOG(INFO) << "Termina VM starting up";
427
428 std::unique_ptr<dbus::Response> dbus_response(
429 dbus::Response::FromMethodCall(method_call));
430
431 dbus::MessageReader reader(method_call);
432 dbus::MessageWriter writer(dbus_response.get());
433
434 patchpanel::TerminaVmStartupRequest request;
435 patchpanel::TerminaVmStartupResponse response;
436
437 if (!reader.PopArrayOfBytesAsProto(&request)) {
438 LOG(ERROR) << "Unable to parse request";
439 writer.AppendProtoAsArrayOfBytes(response);
440 return dbus_response;
441 }
442
443 const int32_t cid = request.cid();
444 if (!StartTerminaVm(cid)) {
445 LOG(ERROR) << "Failed to start Termina VM network service";
446 writer.AppendProtoAsArrayOfBytes(response);
447 return dbus_response;
448 }
449
450 // Populate the response with the known devices.
451 auto build_resp = [](int32_t cid, patchpanel::TerminaVmStartupResponse* resp,
452 Device* device) {
453 auto* ctx = dynamic_cast<CrostiniService::Context*>(device->context());
454 if (!ctx || ctx->TAP().empty() || ctx->CID() != cid)
455 return;
456
457 const auto& config = device->config();
458 auto* dev = resp->mutable_device();
459 dev->set_ifname(ctx->TAP());
460 const auto* subnet = config.ipv4_subnet();
461 if (!subnet) {
462 LOG(ERROR) << "Missing required subnet for " << device->ifname();
463 return;
464 }
465 auto* resp_subnet = dev->mutable_ipv4_subnet();
466 resp_subnet->set_base_addr(subnet->BaseAddress());
467 resp_subnet->set_prefix_len(subnet->PrefixLength());
468 subnet = config.lxd_ipv4_subnet();
469 if (!subnet) {
470 LOG(ERROR) << "Missing required lxd subnet for " << device->ifname();
471 return;
472 }
473 resp_subnet = resp->mutable_container_subnet();
474 resp_subnet->set_base_addr(subnet->BaseAddress());
475 resp_subnet->set_prefix_len(subnet->PrefixLength());
476 };
477
478 device_mgr_->ProcessDevices(
479 base::Bind(build_resp, cid, base::Unretained(&response)));
480
481 writer.AppendProtoAsArrayOfBytes(response);
482 return dbus_response;
483}
484
485std::unique_ptr<dbus::Response> Manager::OnTerminaVmShutdown(
486 dbus::MethodCall* method_call) {
487 LOG(INFO) << "Termina VM shutting down";
488
489 std::unique_ptr<dbus::Response> dbus_response(
490 dbus::Response::FromMethodCall(method_call));
491
492 dbus::MessageReader reader(method_call);
493 dbus::MessageWriter writer(dbus_response.get());
494
495 patchpanel::TerminaVmShutdownRequest request;
496 patchpanel::TerminaVmShutdownResponse response;
497
498 if (!reader.PopArrayOfBytesAsProto(&request)) {
499 LOG(ERROR) << "Unable to parse request";
500 writer.AppendProtoAsArrayOfBytes(response);
501 return dbus_response;
502 }
503
504 StopTerminaVm(request.cid());
505
506 writer.AppendProtoAsArrayOfBytes(response);
507 return dbus_response;
508}
509
Garrick Evanse94a14e2019-11-11 10:32:13 +0900510void Manager::SendGuestMessage(const GuestMessage& msg) {
Garrick Evans96e03042019-05-28 14:30:52 +0900511 IpHelperMessage ipm;
512 *ipm.mutable_guest_message() = msg;
Garrick Evans96e03042019-05-28 14:30:52 +0900513 adb_proxy_->SendMessage(ipm);
Garrick Evanse94a14e2019-11-11 10:32:13 +0900514 mcast_proxy_->SendMessage(ipm);
515 nd_proxy_->SendMessage(ipm);
Garrick Evans96e03042019-05-28 14:30:52 +0900516}
517
Kevin Cernekee95d4ae92016-06-19 10:26:29 -0700518} // namespace arc_networkd