blob: b85cf7c9fa31143cd8f445ede3456e4aa715befd [file] [log] [blame]
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "common/libs/fs/shared_fd.h"
17
18#include <sys/types.h>
19#include <sys/stat.h>
Cody Schuffelen2a4746f2019-08-28 12:46:45 -070020#include <sys/mman.h>
21#include <sys/syscall.h>
Ping-Hao Wu75cc1e02017-06-06 16:39:14 -070022#include <cstddef>
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070023#include <errno.h>
24#include <fcntl.h>
25#include <netinet/in.h>
26#include <unistd.h>
Jorge E. Moreiracfbb4102018-07-02 18:53:24 -070027#include <algorithm>
Cody Schuffelen4ede79d2019-11-13 13:24:12 -080028#include <vector>
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070029
Greg Hartman40b88f52017-06-22 15:34:11 -070030#include "common/libs/glog/logging.h"
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070031#include "common/libs/fs/shared_select.h"
32
33// #define ENABLE_GCE_SHARED_FD_LOGGING 1
34
35namespace {
Greg Hartman153b1062017-11-11 12:09:21 -080036using cvd::SharedFDSet;
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070037
38void MarkAll(const SharedFDSet& input, fd_set* dest, int* max_index) {
39 for (SharedFDSet::const_iterator it = input.begin(); it != input.end();
40 ++it) {
41 (*it)->Set(dest, max_index);
42 }
43}
44
Tomasz Wiszkowski09c17782017-09-15 09:54:49 -070045void CheckMarked(fd_set* in_out_mask, SharedFDSet* in_out_set) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070046 if (!in_out_set) {
47 return;
48 }
49 SharedFDSet save;
50 save.swap(in_out_set);
51 for (SharedFDSet::iterator it = save.begin(); it != save.end(); ++it) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070052 if ((*it)->IsSet(in_out_mask)) {
53 in_out_set->Set(*it);
54 }
55 }
56}
Cody Schuffelen2a4746f2019-08-28 12:46:45 -070057
58/*
59 * Android currently has host prebuilts of glibc 2.15 and 2.17, but
60 * memfd_create was only added in glibc 2.27. It was defined in Linux 3.17,
61 * so we consider it safe to use the low-level arbitrary syscall wrapper.
62 */
63#ifndef __NR_memfd_create
64# if defined(__x86_64__)
65# define __NR_memfd_create 319
66# elif defined(__i386__)
67# define __NR_memfd_create 356
68# elif defined(__aarch64__)
69# define __NR_memfd_create 279
70# else
71/* No interest in other architectures. */
72# error "Unknown architecture."
73# endif
74#endif
75
76int memfd_create_wrapper(const char* name, unsigned int flags) {
77#ifdef CUTTLEFISH_HOST
78 // TODO(schuffelen): Use memfd_create with a newer host libc.
79 return syscall(__NR_memfd_create, name, flags);
80#else
81 return memfd_create(name, flags);
82#endif
83}
84
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070085} // namespace
86
Greg Hartman153b1062017-11-11 12:09:21 -080087namespace cvd {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070088
89bool FileInstance::CopyFrom(FileInstance& in) {
Cody Schuffelen4ede79d2019-11-13 13:24:12 -080090 std::vector<char> buffer(8192);
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -070091 while (true) {
92 ssize_t num_read = in.Read(buffer.data(), buffer.size());
93 if (!num_read) {
94 return true;
95 }
96 if (num_read == -1) {
97 return false;
98 }
99 if (num_read > 0) {
100 if (Write(buffer.data(), num_read) != num_read) {
101 // The caller will have to log an appropriate message.
102 return false;
103 }
104 }
105 }
106 return true;
107}
108
Jorge E. Moreiracfbb4102018-07-02 18:53:24 -0700109bool FileInstance::CopyFrom(FileInstance& in, size_t length) {
Cody Schuffelen4ede79d2019-11-13 13:24:12 -0800110 std::vector<char> buffer(8192);
Jorge E. Moreiracfbb4102018-07-02 18:53:24 -0700111 while (length > 0) {
112 ssize_t num_read = in.Read(buffer.data(), std::min(buffer.size(), length));
113 length -= num_read;
114 if (num_read <= 0) {
115 return false;
116 }
117 if (Write(buffer.data(), num_read) != num_read) {
118 // The caller will have to log an appropriate message.
119 return false;
120 }
121 }
122 return true;
123}
124
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700125void FileInstance::Close() {
Cody Schuffelen4ede79d2019-11-13 13:24:12 -0800126 std::stringstream message;
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700127 if (fd_ == -1) {
128 errno_ = EBADF;
129 } else if (close(fd_) == -1) {
130 errno_ = errno;
131 if (identity_.size()) {
Cody Schuffelen4ede79d2019-11-13 13:24:12 -0800132 message << __FUNCTION__ << ": " << identity_ << " failed (" << StrError() << ")";
133 std::string message_str = message.str();
134 Log(message_str.c_str());
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700135 }
136 } else {
137 if (identity_.size()) {
Cody Schuffelen4ede79d2019-11-13 13:24:12 -0800138 message << __FUNCTION__ << ": " << identity_ << "succeeded";
139 std::string message_str = message.str();
140 Log(message_str.c_str());
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700141 }
142 }
143 fd_ = -1;
144}
145
146void FileInstance::Identify(const char* identity) {
Cody Schuffelen4ede79d2019-11-13 13:24:12 -0800147 std::stringstream identity_stream;
148 identity_stream << "fd=" << fd_ << " @" << this << " is " << identity;
149 identity_ = identity_stream.str();
150 std::stringstream message;
151 message << __FUNCTION__ << ": " << identity_;
152 std::string message_str = message.str();
153 Log(message_str.c_str());
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700154}
155
156bool FileInstance::IsSet(fd_set* in) const {
157 if (IsOpen() && FD_ISSET(fd_, in)) {
158 return true;
159 }
160 return false;
161}
162
163#if ENABLE_GCE_SHARED_FD_LOGGING
164void FileInstance::Log(const char* message) {
Greg Hartman67fa8582017-07-31 21:40:02 -0700165 LOG(INFO) << message;
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700166}
167#else
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700168void FileInstance::Log(const char*) {}
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700169#endif
170
171void FileInstance::Set(fd_set* dest, int* max_index) const {
172 if (!IsOpen()) {
173 return;
174 }
175 if (fd_ >= *max_index) {
176 *max_index = fd_ + 1;
177 }
178 FD_SET(fd_, dest);
179}
180
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700181int Select(SharedFDSet* read_set, SharedFDSet* write_set,
182 SharedFDSet* error_set, struct timeval* timeout) {
183 int max_index = 0;
184 fd_set readfds;
185 FD_ZERO(&readfds);
186 if (read_set) {
187 MarkAll(*read_set, &readfds, &max_index);
188 }
189 fd_set writefds;
190 FD_ZERO(&writefds);
191 if (write_set) {
192 MarkAll(*write_set, &writefds, &max_index);
193 }
194 fd_set errorfds;
195 FD_ZERO(&errorfds);
Tomasz Wiszkowski09c17782017-09-15 09:54:49 -0700196 if (error_set) {
197 MarkAll(*error_set, &errorfds, &max_index);
198 }
199
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700200 int rval = TEMP_FAILURE_RETRY(
201 select(max_index, &readfds, &writefds, &errorfds, timeout));
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700202 FileInstance::Log("select\n");
Tomasz Wiszkowski09c17782017-09-15 09:54:49 -0700203 CheckMarked(&readfds, read_set);
204 CheckMarked(&writefds, write_set);
205 CheckMarked(&errorfds, error_set);
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700206 return rval;
207}
208
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700209static void MakeAddress(const char* name, bool abstract,
210 struct sockaddr_un* dest, socklen_t* len) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700211 memset(dest, 0, sizeof(*dest));
212 dest->sun_family = AF_UNIX;
213 // sun_path is NOT expected to be nul-terminated.
214 // See man 7 unix.
Ping-Hao Wu75cc1e02017-06-06 16:39:14 -0700215 size_t namelen;
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700216 if (abstract) {
Ping-Hao Wu75cc1e02017-06-06 16:39:14 -0700217 // ANDROID_SOCKET_NAMESPACE_ABSTRACT
218 namelen = strlen(name);
219 CHECK_LE(namelen, sizeof(dest->sun_path) - 1)
220 << "MakeAddress failed. Name=" << name << " is longer than allowed.";
221 dest->sun_path[0] = 0;
222 memcpy(dest->sun_path + 1, name, namelen);
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700223 } else {
Ping-Hao Wu75cc1e02017-06-06 16:39:14 -0700224 // ANDROID_SOCKET_NAMESPACE_RESERVED
225 // ANDROID_SOCKET_NAMESPACE_FILESYSTEM
226 // TODO(pinghao): Distinguish between them?
227 namelen = strlen(name);
228 CHECK_LE(namelen, sizeof(dest->sun_path))
229 << "MakeAddress failed. Name=" << name << " is longer than allowed.";
230 strncpy(dest->sun_path, name, strlen(name));
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700231 }
Ping-Hao Wu75cc1e02017-06-06 16:39:14 -0700232 *len = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700233}
234
235SharedFD SharedFD::SocketSeqPacketServer(const char* name, mode_t mode) {
236 return SocketLocalServer(name, false, SOCK_SEQPACKET, mode);
237}
238
239SharedFD SharedFD::SocketSeqPacketClient(const char* name) {
240 return SocketLocalClient(name, false, SOCK_SEQPACKET);
241}
242
Tomasz Wiszkowskiaf38c7c2017-08-14 12:33:11 -0700243SharedFD SharedFD::TimerFD(int clock, int flags) {
244 int fd = timerfd_create(clock, flags);
245 if (fd == -1) {
246 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, errno)));
247 } else {
248 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, 0)));
249 }
250}
251
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700252SharedFD SharedFD::Accept(const FileInstance& listener, struct sockaddr* addr,
253 socklen_t* addrlen) {
254 return SharedFD(
255 std::shared_ptr<FileInstance>(listener.Accept(addr, addrlen)));
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700256}
257
258SharedFD SharedFD::Accept(const FileInstance& listener) {
259 return SharedFD::Accept(listener, NULL, NULL);
260}
261
Greg Hartman3c95aac2017-06-14 18:24:26 -0700262SharedFD SharedFD::Dup(int unmanaged_fd) {
Cody Schuffelen213600a2019-11-18 18:52:59 -0800263 int fd = fcntl(unmanaged_fd, F_DUPFD_CLOEXEC, 3);
264 int error_num = errno;
265 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, error_num)));
Greg Hartman3c95aac2017-06-14 18:24:26 -0700266}
267
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700268bool SharedFD::Pipe(SharedFD* fd0, SharedFD* fd1) {
269 int fds[2];
270 int rval = pipe(fds);
271 if (rval != -1) {
272 (*fd0) = std::shared_ptr<FileInstance>(new FileInstance(fds[0], errno));
273 (*fd1) = std::shared_ptr<FileInstance>(new FileInstance(fds[1], errno));
274 return true;
275 }
276 return false;
277}
278
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700279SharedFD SharedFD::Event(int initval, int flags) {
Cody Schuffelenb11b4602019-08-28 16:04:33 -0700280 int fd = eventfd(initval, flags);
281 return std::shared_ptr<FileInstance>(new FileInstance(fd, errno));
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700282}
283
Tomasz Wiszkowski16fb1742017-09-15 14:31:53 -0700284SharedFD SharedFD::Epoll(int flags) {
Cody Schuffelenb11b4602019-08-28 16:04:33 -0700285 int fd = epoll_create1(flags);
286 return std::shared_ptr<FileInstance>(new FileInstance(fd, errno));
Tomasz Wiszkowski16fb1742017-09-15 14:31:53 -0700287}
288
Cody Schuffelen2a4746f2019-08-28 12:46:45 -0700289SharedFD SharedFD::MemfdCreate(const char* name, unsigned int flags) {
290 int fd = memfd_create_wrapper(name, flags);
291 int error_num = errno;
292 return std::shared_ptr<FileInstance>(new FileInstance(fd, error_num));
293}
294
Jorge E. Moreira8e9793e2018-11-05 21:57:26 -0800295bool SharedFD::SocketPair(int domain, int type, int protocol,
296 SharedFD* fd0, SharedFD* fd1) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700297 int fds[2];
298 int rval = socketpair(domain, type, protocol, fds);
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700299 if (rval != -1) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700300 (*fd0) = std::shared_ptr<FileInstance>(new FileInstance(fds[0], errno));
301 (*fd1) = std::shared_ptr<FileInstance>(new FileInstance(fds[1], errno));
302 return true;
303 }
304 return false;
305}
306
307SharedFD SharedFD::Open(const char* path, int flags, mode_t mode) {
308 int fd = TEMP_FAILURE_RETRY(open(path, flags, mode));
309 if (fd == -1) {
310 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, errno)));
311 } else {
312 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, 0)));
313 }
314}
315
Jorge E. Moreira6d7753e2018-07-18 11:28:48 -0700316SharedFD SharedFD::Creat(const char* path, mode_t mode) {
317 return SharedFD::Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
318}
319
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700320SharedFD SharedFD::Socket(int domain, int socket_type, int protocol) {
321 int fd = TEMP_FAILURE_RETRY(socket(domain, socket_type, protocol));
322 if (fd == -1) {
323 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, errno)));
324 } else {
325 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, 0)));
326 }
327}
328
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800329SharedFD SharedFD::ErrorFD(int error) {
330 return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(-1, error)));
331}
332
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700333SharedFD SharedFD::SocketLocalClient(const char* name, bool abstract,
334 int in_type) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700335 struct sockaddr_un addr;
Ping-Hao Wu75cc1e02017-06-06 16:39:14 -0700336 socklen_t addrlen;
337 MakeAddress(name, abstract, &addr, &addrlen);
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700338 SharedFD rval = SharedFD::Socket(PF_UNIX, in_type, 0);
339 if (!rval->IsOpen()) {
340 return rval;
341 }
Ryan Haininge451e9d2018-05-09 17:02:32 -0700342 if (rval->Connect(reinterpret_cast<sockaddr*>(&addr), addrlen) == -1) {
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800343 return SharedFD::ErrorFD(rval->GetErrno());
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700344 }
345 return rval;
346}
347
Ryan Hainingd5c1bde2018-01-29 13:34:22 -0800348SharedFD SharedFD::SocketLocalClient(int port, int type) {
349 sockaddr_in addr{};
350 addr.sin_family = AF_INET;
351 addr.sin_port = htons(port);
352 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
353 SharedFD rval = SharedFD::Socket(AF_INET, type, 0);
354 if (!rval->IsOpen()) {
355 return rval;
356 }
357 if (rval->Connect(reinterpret_cast<const sockaddr*>(&addr),
358 sizeof addr) < 0) {
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800359 return SharedFD::ErrorFD(rval->GetErrno());
Ryan Hainingd5c1bde2018-01-29 13:34:22 -0800360 }
361 return rval;
362}
363
Jorge E. Moreira854bcbc2017-09-26 16:05:10 -0700364SharedFD SharedFD::SocketLocalServer(int port, int type) {
365 struct sockaddr_in addr;
366 memset(&addr, 0, sizeof(addr));
367 addr.sin_family = AF_INET;
368 addr.sin_port = htons(port);
369 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
370 SharedFD rval = SharedFD::Socket(AF_INET, type, 0);
371 if(!rval->IsOpen()) {
372 return rval;
373 }
374 int n = 1;
375 if (rval->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1) {
376 LOG(ERROR) << "SetSockOpt failed " << rval->StrError();
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800377 return SharedFD::ErrorFD(rval->GetErrno());
Jorge E. Moreira854bcbc2017-09-26 16:05:10 -0700378 }
Ryan Haininge451e9d2018-05-09 17:02:32 -0700379 if(rval->Bind(reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
Jorge E. Moreira854bcbc2017-09-26 16:05:10 -0700380 LOG(ERROR) << "Bind failed " << rval->StrError();
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800381 return SharedFD::ErrorFD(rval->GetErrno());
Jorge E. Moreira854bcbc2017-09-26 16:05:10 -0700382 }
383 if (type == SOCK_STREAM) {
384 if (rval->Listen(4) < 0) {
385 LOG(ERROR) << "Listen failed " << rval->StrError();
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800386 return SharedFD::ErrorFD(rval->GetErrno());
Jorge E. Moreira854bcbc2017-09-26 16:05:10 -0700387 }
388 }
389 return rval;
390}
391
Tomasz Wiszkowskid88403b2017-07-06 14:42:14 -0700392SharedFD SharedFD::SocketLocalServer(const char* name, bool abstract,
393 int in_type, mode_t mode) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700394 // DO NOT UNLINK addr.sun_path. It does NOT have to be null-terminated.
395 // See man 7 unix for more details.
396 if (!abstract) (void)unlink(name);
397
398 struct sockaddr_un addr;
Ping-Hao Wu75cc1e02017-06-06 16:39:14 -0700399 socklen_t addrlen;
400 MakeAddress(name, abstract, &addr, &addrlen);
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700401 SharedFD rval = SharedFD::Socket(PF_UNIX, in_type, 0);
402 if (!rval->IsOpen()) {
403 return rval;
404 }
405
406 int n = 1;
407 if (rval->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1) {
408 LOG(ERROR) << "SetSockOpt failed " << rval->StrError();
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800409 return SharedFD::ErrorFD(rval->GetErrno());
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700410 }
Ryan Haininge451e9d2018-05-09 17:02:32 -0700411 if (rval->Bind(reinterpret_cast<sockaddr*>(&addr), addrlen) == -1) {
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700412 LOG(ERROR) << "Bind failed; name=" << name << ": " << rval->StrError();
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800413 return SharedFD::ErrorFD(rval->GetErrno());
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700414 }
415
416 /* Only the bottom bits are really the socket type; there are flags too. */
417 constexpr int SOCK_TYPE_MASK = 0xf;
418
419 // Connection oriented sockets: start listening.
420 if ((in_type & SOCK_TYPE_MASK) == SOCK_STREAM) {
421 // Follows the default from socket_local_server
422 if (rval->Listen(1) == -1) {
423 LOG(ERROR) << "Listen failed: " << rval->StrError();
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800424 return SharedFD::ErrorFD(rval->GetErrno());
Tomasz Wiszkowskia449e9c2017-05-25 14:30:56 -0700425 }
426 }
427
428 if (!abstract) {
429 if (TEMP_FAILURE_RETRY(chmod(name, mode)) == -1) {
430 LOG(ERROR) << "chmod failed: " << strerror(errno);
431 // However, continue since we do have a listening socket
432 }
433 }
434 return rval;
435}
436
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800437SharedFD SharedFD::VsockServer(unsigned int port, int type) {
438 auto vsock = cvd::SharedFD::Socket(AF_VSOCK, type, 0);
439 if (!vsock->IsOpen()) {
440 return vsock;
441 }
442 sockaddr_vm addr{};
443 addr.svm_family = AF_VSOCK;
444 addr.svm_port = port;
445 addr.svm_cid = VMADDR_CID_ANY;
446 auto casted_addr = reinterpret_cast<sockaddr*>(&addr);
447 if (vsock->Bind(casted_addr, sizeof(addr)) == -1) {
448 LOG(ERROR) << "Bind failed (" << vsock->StrError() << ")";
449 return SharedFD::ErrorFD(vsock->GetErrno());
450 }
451 if (type == SOCK_STREAM) {
452 if (vsock->Listen(4) < 0) {
453 LOG(ERROR) << "Listen failed (" << vsock->StrError() << ")";
454 return SharedFD::ErrorFD(vsock->GetErrno());
455 }
456 }
457 return vsock;
458}
459
Cody Schuffelen14ecb072019-11-26 17:59:33 -0800460SharedFD SharedFD::VsockServer(int type) {
461 return VsockServer(VMADDR_PORT_ANY, type);
462}
463
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800464SharedFD SharedFD::VsockClient(unsigned int cid, unsigned int port, int type) {
465 auto vsock = cvd::SharedFD::Socket(AF_VSOCK, type, 0);
466 if (!vsock->IsOpen()) {
467 return vsock;
468 }
469 sockaddr_vm addr{};
470 addr.svm_family = AF_VSOCK;
471 addr.svm_port = port;
472 addr.svm_cid = cid;
473 auto casted_addr = reinterpret_cast<sockaddr*>(&addr);
474 if (vsock->Connect(casted_addr, sizeof(addr)) == -1) {
Cody Schuffelenfa69c382018-12-17 18:57:36 -0800475 return SharedFD::ErrorFD(vsock->GetErrno());
476 }
477 return vsock;
478}
479
Greg Hartman153b1062017-11-11 12:09:21 -0800480} // namespace cvd