blob: dc1d0e5111ea266598d44eb1454a5cba445ce7d7 [file] [log] [blame]
Garrick Evans3cbac7c2019-04-18 15:31:31 +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/adb_proxy.h"
6
jasongustaman14076282019-05-20 15:38:41 +09007#include <linux/vm_sockets.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +09008#include <sys/socket.h>
9#include <sys/types.h>
Garrick Evansaa4f1ce2019-11-29 13:25:39 +090010#include <sysexits.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090011
12#include <utility>
13
14#include <base/bind.h>
15#include <base/logging.h>
16#include <base/strings/stringprintf.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090017
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +090018#include "arc/network/minijailed_process_runner.h"
Hugo Benichi2ac4d072019-05-28 14:51:23 +090019#include "arc/network/net_util.h"
20
Garrick Evans3cbac7c2019-04-18 15:31:31 +090021namespace arc_networkd {
22namespace {
Garrick Evansa7556db2019-05-07 11:22:40 +090023// adb gets confused if we listen on 5555 and thinks there is an emulator
24// running, which in turn ends up confusing our integration test libraries
25// because multiple devices show up.
26constexpr uint16_t kTcpListenPort = 5550;
27// But we still connect to adbd on its standard TCP port.
28constexpr uint16_t kTcpConnectPort = 5555;
Hugo Benichi2ac4d072019-05-28 14:51:23 +090029constexpr uint32_t kTcpAddr = Ipv4Addr(100, 115, 92, 2);
jasongustaman14076282019-05-20 15:38:41 +090030constexpr uint32_t kVsockPort = 5555;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090031constexpr int kMaxConn = 16;
32
33} // namespace
34
Garrick Evans96e03042019-05-28 14:30:52 +090035AdbProxy::AdbProxy(base::ScopedFD control_fd)
Garrick Evansbdf1f982019-06-07 09:46:49 +090036 : msg_dispatcher_(std::move(control_fd)),
Garrick Evans1cce71a2019-06-21 10:43:14 +090037 arc_type_(GuestMessage::UNKNOWN_GUEST),
38 arcvm_vsock_cid_(-1) {
Garrick Evans96e03042019-05-28 14:30:52 +090039 msg_dispatcher_.RegisterFailureHandler(
40 base::Bind(&AdbProxy::OnParentProcessExit, weak_factory_.GetWeakPtr()));
41
42 msg_dispatcher_.RegisterGuestMessageHandler(
43 base::Bind(&AdbProxy::OnGuestMessage, weak_factory_.GetWeakPtr()));
44}
Garrick Evans3cbac7c2019-04-18 15:31:31 +090045
Hidehiko Abede129222019-08-16 00:55:04 +090046AdbProxy::~AdbProxy() = default;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090047
48int AdbProxy::OnInit() {
49 // Prevent the main process from sending us any signals.
50 if (setsid() < 0) {
51 PLOG(ERROR) << "Failed to created a new session with setsid; exiting";
Garrick Evansaa4f1ce2019-11-29 13:25:39 +090052 return EX_OSERR;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090053 }
54
Jason Jeremy Imand89b5f52019-10-24 10:39:17 +090055 EnterChildProcessJail();
Garrick Evans3cbac7c2019-04-18 15:31:31 +090056 return Daemon::OnInit();
57}
58
Garrick Evansbdf1f982019-06-07 09:46:49 +090059void AdbProxy::Reset() {
Hidehiko Abede129222019-08-16 00:55:04 +090060 src_watcher_.reset();
Garrick Evansbdf1f982019-06-07 09:46:49 +090061 src_.reset();
62 fwd_.clear();
Garrick Evans1cce71a2019-06-21 10:43:14 +090063 arcvm_vsock_cid_ = -1;
64 arc_type_ = GuestMessage::UNKNOWN_GUEST;
Garrick Evansbdf1f982019-06-07 09:46:49 +090065}
66
Garrick Evans96e03042019-05-28 14:30:52 +090067void AdbProxy::OnParentProcessExit() {
68 LOG(ERROR) << "Quitting because the parent process died";
Garrick Evansbdf1f982019-06-07 09:46:49 +090069 Reset();
Garrick Evans96e03042019-05-28 14:30:52 +090070 Quit();
71}
72
Hidehiko Abede129222019-08-16 00:55:04 +090073void AdbProxy::OnFileCanReadWithoutBlocking() {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090074 if (auto conn = src_->Accept()) {
75 if (auto dst = Connect()) {
76 LOG(INFO) << "Connection established: " << *conn << " <-> " << *dst;
77 auto fwd = std::make_unique<SocketForwarder>(
78 base::StringPrintf("adbp%d-%d", conn->fd(), dst->fd()),
79 std::move(conn), std::move(dst));
80 fwd->Start();
81 fwd_.emplace_back(std::move(fwd));
82 }
83 }
84
85 // Cleanup any defunct forwarders.
86 for (auto it = fwd_.begin(); it != fwd_.end();) {
Garrick Evans088cd0e2019-06-04 15:20:43 +090087 if (!(*it)->IsRunning() && (*it)->HasBeenStarted())
Garrick Evans3cbac7c2019-04-18 15:31:31 +090088 it = fwd_.erase(it);
Garrick Evans4e96fad2019-05-17 10:19:38 +090089 else
90 ++it;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090091 }
92}
93
94std::unique_ptr<Socket> AdbProxy::Connect() const {
Garrick Evansbdf1f982019-06-07 09:46:49 +090095 switch (arc_type_) {
Garrick Evans1cce71a2019-06-21 10:43:14 +090096 case GuestMessage::ARC:
97 case GuestMessage::ARC_LEGACY: {
Garrick Evansbdf1f982019-06-07 09:46:49 +090098 struct sockaddr_in addr_in = {0};
99 addr_in.sin_family = AF_INET;
100 addr_in.sin_port = htons(kTcpConnectPort);
101 addr_in.sin_addr.s_addr = kTcpAddr;
102 auto dst = std::make_unique<Socket>(AF_INET, SOCK_STREAM);
103 return dst->Connect((const struct sockaddr*)&addr_in, sizeof(addr_in))
104 ? std::move(dst)
105 : nullptr;
106 }
107 case GuestMessage::ARC_VM: {
108 struct sockaddr_vm addr_vm = {0};
109 addr_vm.svm_family = AF_VSOCK;
110 addr_vm.svm_port = kVsockPort;
Garrick Evans1cce71a2019-06-21 10:43:14 +0900111 addr_vm.svm_cid = arcvm_vsock_cid_;
Garrick Evansbdf1f982019-06-07 09:46:49 +0900112 auto dst = std::make_unique<Socket>(AF_VSOCK, SOCK_STREAM);
113 return dst->Connect((const struct sockaddr*)&addr_vm, sizeof(addr_vm))
114 ? std::move(dst)
115 : nullptr;
116 }
117 default:
118 LOG(DFATAL) << "Unexpected connect - no ARC guest";
119 return nullptr;
120 }
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900121}
122
Garrick Evans96e03042019-05-28 14:30:52 +0900123void AdbProxy::OnGuestMessage(const GuestMessage& msg) {
Garrick Evans1cce71a2019-06-21 10:43:14 +0900124 if (msg.type() == GuestMessage::UNKNOWN_GUEST) {
125 LOG(DFATAL) << "Unexpected message from unknown guest";
Garrick Evans96e03042019-05-28 14:30:52 +0900126 return;
Garrick Evans1cce71a2019-06-21 10:43:14 +0900127 }
Garrick Evans96e03042019-05-28 14:30:52 +0900128
Garrick Evansbdf1f982019-06-07 09:46:49 +0900129 arc_type_ = msg.type();
Garrick Evans1cce71a2019-06-21 10:43:14 +0900130 arcvm_vsock_cid_ = msg.arcvm_vsock_cid();
Garrick Evansbdf1f982019-06-07 09:46:49 +0900131
Garrick Evans96e03042019-05-28 14:30:52 +0900132 // On ARC up, start accepting connections.
133 if (msg.event() == GuestMessage::START) {
Garrick Evans584210b2019-05-27 14:25:43 +0900134 src_ = std::make_unique<Socket>(AF_INET, SOCK_STREAM | SOCK_NONBLOCK);
Garrick Evans20cc37c2019-05-29 17:25:59 +0900135 // Need to set this to reuse the port on localhost.
Garrick Evans20cc37c2019-05-29 17:25:59 +0900136 int on = 1;
137 if (setsockopt(src_->fd(), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) <
138 0) {
139 PLOG(ERROR) << "setsockopt(SO_REUSEADDR) failed";
Garrick Evans96e03042019-05-28 14:30:52 +0900140 return;
Garrick Evans20cc37c2019-05-29 17:25:59 +0900141 }
Garrick Evans584210b2019-05-27 14:25:43 +0900142 struct sockaddr_in addr = {0};
143 addr.sin_family = AF_INET;
Garrick Evansa7556db2019-05-07 11:22:40 +0900144 addr.sin_port = htons(kTcpListenPort);
Garrick Evans584210b2019-05-27 14:25:43 +0900145 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
146 if (!src_->Bind((const struct sockaddr*)&addr, sizeof(addr))) {
147 LOG(ERROR) << "Cannot bind source socket";
Garrick Evans96e03042019-05-28 14:30:52 +0900148 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900149 }
150
151 if (!src_->Listen(kMaxConn)) {
152 LOG(ERROR) << "Cannot listen on source socket";
Garrick Evans96e03042019-05-28 14:30:52 +0900153 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900154 }
155
156 // Run the accept loop.
Garrick Evansbdf1f982019-06-07 09:46:49 +0900157 LOG(INFO) << "Accepting connections...";
Hidehiko Abede129222019-08-16 00:55:04 +0900158 src_watcher_ = base::FileDescriptorWatcher::WatchReadable(
159 src_->fd(), base::BindRepeating(&AdbProxy::OnFileCanReadWithoutBlocking,
160 base::Unretained(this)));
Garrick Evans96e03042019-05-28 14:30:52 +0900161 return;
Garrick Evans584210b2019-05-27 14:25:43 +0900162 }
163
Garrick Evans96e03042019-05-28 14:30:52 +0900164 // On ARC down, cull any open connections and stop listening.
165 if (msg.event() == GuestMessage::STOP) {
Garrick Evansbdf1f982019-06-07 09:46:49 +0900166 Reset();
Garrick Evans584210b2019-05-27 14:25:43 +0900167 }
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900168}
169
Garrick Evans3cbac7c2019-04-18 15:31:31 +0900170} // namespace arc_networkd