2 * Copyright (c) 2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/cdefs.h>
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
32 #include <sys/sysctl.h>
33 #include <sys/vsock.h>
36 #include <darwintest.h>
37 #include <darwintest_utils.h>
39 #define COUNT_ELEMS(array) (sizeof (array) / sizeof (array[0]))
42 T_META_RUN_CONCURRENTLY(true),
43 T_META_NAMESPACE("xnu.vsock")
47 vsock_new_socket(void)
49 int sock
= socket(AF_VSOCK
, SOCK_STREAM
, 0);
50 if (sock
< 0 && errno
== ENODEV
) {
51 T_SKIP("no vsock transport available");
53 T_ASSERT_GT(sock
, 0, "create new vsock socket");
58 vsock_get_local_cid(int socket
)
61 int result
= ioctl(socket
, IOCTL_VM_SOCKETS_GET_LOCAL_CID
, &cid
);
62 T_ASSERT_POSIX_SUCCESS(result
, "vsock ioctl cid successful");
63 T_ASSERT_GT(cid
, VMADDR_CID_HOST
, "cid is set");
64 T_ASSERT_NE(cid
, VMADDR_CID_ANY
, "cid is valid");
70 vsock_bind(uint32_t cid
, uint32_t port
, struct sockaddr_vm
* addr
, int *socket
)
72 *socket
= vsock_new_socket();
74 bzero(addr
, sizeof(*addr
));
75 addr
->svm_port
= port
;
78 return bind(*socket
, (struct sockaddr
*) addr
, sizeof(*addr
));
82 vsock_listen(uint32_t cid
, uint32_t port
, struct sockaddr_vm
* addr
, int backlog
, int *socket
)
84 int result
= vsock_bind(cid
, port
, addr
, socket
);
85 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind");
86 return listen(*socket
, backlog
);
90 vsock_connect(uint32_t cid
, uint32_t port
, int *socket
)
92 *socket
= vsock_new_socket();
93 struct sockaddr_vm addr
= (struct sockaddr_vm
) {
97 return connect(*socket
, (struct sockaddr
*)&addr
, sizeof(addr
));
100 static struct sockaddr_vm
101 vsock_getsockname(int socket
)
103 struct sockaddr_vm addr
;
104 socklen_t length
= sizeof(addr
);
105 int result
= getsockname(socket
, (struct sockaddr
*)&addr
, &length
);
106 T_ASSERT_POSIX_SUCCESS(result
, "vsock getsockname");
107 T_ASSERT_EQ_INT((int) sizeof(addr
), length
, "correct address length");
108 T_ASSERT_GT(addr
.svm_port
, 0, "bound to non-zero local port");
113 vsock_close(int socket
)
115 int result
= close(socket
);
116 T_ASSERT_POSIX_SUCCESS(result
, "vsock close");
120 vsock_connect_peers(uint32_t cid
, uint32_t port
, int backlog
, int *socketA
, int *socketB
)
123 struct sockaddr_vm addr
;
125 int result
= vsock_listen(cid
, port
, &addr
, backlog
, &listen_socket
);
126 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen");
128 const uint32_t connection_cid
= vsock_get_local_cid(listen_socket
);
132 result
= vsock_connect(connection_cid
, addr
.svm_port
, &connect_socket
);
133 T_ASSERT_POSIX_SUCCESS(result
, "vsock connect");
136 struct sockaddr_vm accepted_addr
;
137 socklen_t addrlen
= sizeof(accepted_addr
);
138 int accepted_socket
= accept(listen_socket
, (struct sockaddr
*)&accepted_addr
, &addrlen
);
139 T_ASSERT_GT(accepted_socket
, 0, "accepted socket");
140 T_ASSERT_EQ_INT((int) sizeof(accepted_addr
), addrlen
, "correct address length");
141 T_ASSERT_EQ_INT(connection_cid
, accepted_addr
.svm_cid
, "same cid");
142 T_ASSERT_NE_INT(VMADDR_CID_ANY
, accepted_addr
.svm_port
, "some valid port");
143 T_ASSERT_NE_INT(0, accepted_addr
.svm_port
, "some non-zero port");
145 *socketA
= connect_socket
;
146 *socketB
= accepted_socket
;
150 vsock_send(int socket
, char *msg
)
152 T_ASSERT_NOTNULL(msg
, "send message is not null");
153 ssize_t sent_bytes
= send(socket
, msg
, strlen(msg
), 0);
154 T_ASSERT_EQ_LONG(strlen(msg
), (unsigned long)sent_bytes
, "sent all bytes");
158 vsock_disable_sigpipe(int socket
)
161 int result
= setsockopt(socket
, SOL_SOCKET
, SO_NOSIGPIPE
, &on
, sizeof(on
));
162 T_ASSERT_POSIX_SUCCESS(result
, "vsock disable SIGPIPE");
166 vsock_address_exists(struct xvsockpgen
*buffer
, struct sockaddr_vm addr
)
168 struct xvsockpgen
*xvg
= buffer
;
169 struct xvsockpgen
*oxvg
= buffer
;
172 for (xvg
= (struct xvsockpgen
*)((char *)xvg
+ xvg
->xvg_len
);
173 xvg
->xvg_len
> sizeof(struct xvsockpgen
);
174 xvg
= (struct xvsockpgen
*)((char *)xvg
+ xvg
->xvg_len
)) {
175 struct xvsockpcb
*xpcb
= (struct xvsockpcb
*)xvg
;
177 /* Ignore PCBs which were freed during copyout. */
178 if (xpcb
->xvp_gencnt
> oxvg
->xvg_gen
) {
182 if (xpcb
->xvp_local_cid
== addr
.svm_cid
&& xpcb
->xvp_remote_cid
== VMADDR_CID_ANY
&&
183 xpcb
->xvp_local_port
== addr
.svm_port
&& xpcb
->xvp_remote_port
== VMADDR_PORT_ANY
) {
189 T_ASSERT_NE(xvg
, oxvg
, "first and last xvsockpgen were returned");
196 T_DECL(new_socket_getsockname
, "vsock new - getsockname")
198 int socket
= vsock_new_socket();
200 struct sockaddr_vm addr
;
201 socklen_t length
= sizeof(struct sockaddr_vm
);
202 int result
= getsockname(socket
, (struct sockaddr
*)&addr
, &length
);
203 T_ASSERT_POSIX_SUCCESS(result
, "vsock getsockname");
204 T_ASSERT_EQ_INT(addr
.svm_port
, VMADDR_PORT_ANY
, "name is any port");
205 T_ASSERT_EQ_INT(addr
.svm_cid
, VMADDR_CID_ANY
, "name is any cid");
208 T_DECL(new_socket_getpeername
, "vsock new - getpeername")
210 int socket
= vsock_new_socket();
212 struct sockaddr_vm addr
;
213 socklen_t length
= sizeof(struct sockaddr_vm
);
214 int result
= getpeername(socket
, (struct sockaddr
*)&addr
, &length
);
215 T_ASSERT_POSIX_FAILURE(result
, ENOTCONN
, "vsock getpeername");
220 T_DECL(ioctl_cid
, "vsock ioctl cid")
222 int socket
= vsock_new_socket();
223 vsock_get_local_cid(socket
);
228 T_DECL(socketpair
, "vsock socketpair")
231 int error
= socketpair(AF_VSOCK
, SOCK_STREAM
, 0, pair
);
232 if (error
< 0 && errno
== ENODEV
) {
233 T_SKIP("no vsock transport available");
235 T_ASSERT_POSIX_FAILURE(error
, EOPNOTSUPP
, "vsock socketpair not supported");
240 T_DECL(bind
, "vsock bind to specific port")
243 struct sockaddr_vm addr
;
244 int result
= vsock_bind(VMADDR_CID_ANY
, 8888, &addr
, &socket
);
245 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to specific port");
248 T_DECL(bind_any
, "vsock bind to any port")
251 struct sockaddr_vm addr
;
252 int result
= vsock_bind(VMADDR_CID_ANY
, VMADDR_PORT_ANY
, &addr
, &socket
);
253 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to any port");
256 T_DECL(bind_getsockname
, "vsock bind - getsockname")
259 struct sockaddr_vm addr
;
260 const uint32_t port
= VMADDR_PORT_ANY
;
261 const uint32_t cid
= VMADDR_CID_ANY
;
262 int result
= vsock_bind(cid
, port
, &addr
, &socket
);
263 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to any port");
265 struct sockaddr_vm bound_addr
= vsock_getsockname(socket
);
266 T_ASSERT_NE_INT(bound_addr
.svm_port
, port
, "bound to unique local port");
267 T_ASSERT_EQ_INT(bound_addr
.svm_cid
, cid
, "bound to any cid");
270 T_DECL(bind_hypervisor
, "vsock do not bind to hypervisor cid")
273 struct sockaddr_vm addr
;
274 int result
= vsock_bind(VMADDR_CID_HYPERVISOR
, VMADDR_PORT_ANY
, &addr
, &socket
);
275 T_ASSERT_POSIX_FAILURE(result
, EADDRNOTAVAIL
, "vsock do not bind to hypervisor cid");
278 T_DECL(bind_reserved
, "vsock do not bind to reserved cid")
281 struct sockaddr_vm addr
;
282 int result
= vsock_bind(VMADDR_CID_RESERVED
, VMADDR_PORT_ANY
, &addr
, &socket
);
283 T_ASSERT_POSIX_FAILURE(result
, EADDRNOTAVAIL
, "vsock do not bind to reserved cid");
286 T_DECL(bind_host
, "vsock do not bind to host cid")
289 struct sockaddr_vm addr
;
290 int result
= vsock_bind(VMADDR_CID_HOST
, VMADDR_PORT_ANY
, &addr
, &socket
);
291 T_ASSERT_POSIX_FAILURE(result
, EADDRNOTAVAIL
, "vsock do not bind to host cid");
294 T_DECL(bind_zero
, "vsock bind to port zero", T_META_ASROOT(true))
296 const uint32_t port
= 0;
299 struct sockaddr_vm addr
;
300 int result
= vsock_bind(VMADDR_CID_ANY
, port
, &addr
, &socket
);
301 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to port zero");
303 struct sockaddr_vm bound_addr
;
304 socklen_t length
= sizeof(struct sockaddr_vm
);
305 result
= getsockname(socket
, (struct sockaddr
*)&bound_addr
, &length
);
306 T_ASSERT_POSIX_SUCCESS(result
, "vsock getsockname");
307 T_ASSERT_EQ_INT((int) sizeof(bound_addr
), length
, "correct address length");
308 T_ASSERT_EQ_UINT(bound_addr
.svm_port
, port
, "bound to local port zero");
311 T_DECL(bind_double
, "vsock double bind")
313 const uint32_t cid
= VMADDR_CID_ANY
;
314 const uint32_t port
= 8899;
317 struct sockaddr_vm addr
;
318 int result
= vsock_bind(cid
, port
, &addr
, &socket
);
319 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to a port");
321 result
= bind(socket
, (struct sockaddr
*) &addr
, sizeof(addr
));
322 T_ASSERT_POSIX_FAILURE(result
, EINVAL
, "vsock bind to same port");
325 T_DECL(bind_same
, "vsock bind same address and port")
327 const uint32_t cid
= VMADDR_CID_ANY
;
328 const uint32_t port
= 3399;
331 struct sockaddr_vm addr
;
332 int result
= vsock_bind(cid
, port
, &addr
, &socket
);
333 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to a port");
335 result
= vsock_bind(cid
, port
, &addr
, &socket
);
336 T_ASSERT_POSIX_FAILURE(result
, EADDRINUSE
, "vsock bind to same address and port");
339 T_DECL(bind_port_reuse
, "vsock bind port reuse")
341 const uint32_t cid
= VMADDR_CID_ANY
;
342 const uint32_t port
= 9111;
345 struct sockaddr_vm addr
;
346 int result
= vsock_bind(cid
, port
, &addr
, &socket
);
347 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to a port");
351 result
= vsock_bind(cid
, port
, &addr
, &socket
);
352 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind to a port");
355 T_DECL(bind_privileged_non_root
, "vsock bind on privileged port - non-root", T_META_ASROOT(false))
357 if (geteuid() == 0) {
358 T_SKIP("test requires non-root privileges to run.");
360 struct sockaddr_vm addr
;
362 int result
= vsock_bind(VMADDR_CID_ANY
, 5, &addr
, &socket
);
363 T_ASSERT_POSIX_FAILURE(result
, EACCES
, "vsock bind privileged as non-root");
366 T_DECL(bind_privileged_root
, "vsock bind on privileged port - root", T_META_ASROOT(true))
368 if (geteuid() != 0) {
369 T_SKIP("test requires root privileges to run.");
371 struct sockaddr_vm addr
;
373 int result
= vsock_bind(VMADDR_CID_ANY
, 6, &addr
, &socket
);
374 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind privileged as root");
377 T_DECL(bind_no_family
, "vsock bind with unspecified family")
379 int socket
= vsock_new_socket();
381 struct sockaddr_vm addr
= (struct sockaddr_vm
) {
382 .svm_family
= AF_UNSPEC
,
383 .svm_cid
= VMADDR_CID_ANY
,
387 int result
= bind(socket
, (struct sockaddr
*) &addr
, sizeof(addr
));
388 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind with unspecified family");
391 T_DECL(bind_vsock_family
, "vsock bind with vsock family")
393 int socket
= vsock_new_socket();
395 struct sockaddr_vm addr
= (struct sockaddr_vm
) {
396 .svm_family
= AF_VSOCK
,
397 .svm_cid
= VMADDR_CID_ANY
,
401 int result
= bind(socket
, (struct sockaddr
*) &addr
, sizeof(addr
));
402 T_ASSERT_POSIX_SUCCESS(result
, "vsock bind with vsock family");
405 T_DECL(bind_wrong_family
, "vsock bind with wrong family")
407 int socket
= vsock_new_socket();
409 struct sockaddr_vm addr
= (struct sockaddr_vm
) {
410 .svm_family
= AF_INET
,
411 .svm_cid
= VMADDR_CID_ANY
,
415 int result
= bind(socket
, (struct sockaddr
*) &addr
, sizeof(addr
));
416 T_ASSERT_POSIX_FAILURE(result
, EAFNOSUPPORT
, "vsock bind with wrong family");
421 T_DECL(listen
, "vsock listen on specific port")
423 struct sockaddr_vm addr
;
425 int result
= vsock_listen(VMADDR_CID_ANY
, 8889, &addr
, 10, &socket
);
426 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen");
429 T_DECL(listen_any
, "vsock listen on any port")
431 struct sockaddr_vm addr
;
433 int result
= vsock_listen(VMADDR_CID_ANY
, VMADDR_PORT_ANY
, &addr
, 10, &socket
);
434 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen");
439 T_DECL(connect_non_hypervisor
, "vsock connect to remote other than hypervisor")
442 int result
= vsock_connect(5555, 1234, &socket
);
443 T_ASSERT_POSIX_FAILURE(result
, EFAULT
, "vsock connect non-hypervisor");
446 T_DECL(connect_non_listening_host
, "vsock connect to non-listening host port")
449 int result
= vsock_connect(VMADDR_CID_HOST
, 7777, &socket
);
450 T_ASSERT_POSIX_FAILURE(result
, EAGAIN
, "vsock connect non-listening host port");
453 T_DECL(connect_non_listening_hypervisor
, "vsock connect to non-listening hypervisor port")
456 int result
= vsock_connect(VMADDR_CID_HYPERVISOR
, 4444, &socket
);
457 T_ASSERT_POSIX_FAILURE(result
, EAGAIN
, "vsock connect non-listening hypervisor port");
460 T_DECL(connect_getsockname
, "vsock connect - getsockname")
463 int result
= vsock_connect(VMADDR_CID_HOST
, 9999, &socket
);
464 T_ASSERT_POSIX_FAILURE(result
, EAGAIN
, "vsock connect non-listening");
466 vsock_getsockname(socket
);
469 T_DECL(connect_timeout
, "vsock connect with timeout")
471 int socket
= vsock_new_socket();
473 struct timeval timeout
= (struct timeval
) {
477 int result
= setsockopt(socket
, SOL_SOCKET
, SO_SNDTIMEO
, &timeout
, sizeof(timeout
));
478 T_ASSERT_POSIX_SUCCESS(result
, "vsock set socket timeout");
480 struct sockaddr_vm addr
= (struct sockaddr_vm
) {
481 .svm_cid
= VMADDR_CID_HOST
,
484 result
= connect(socket
, (struct sockaddr
*)&addr
, sizeof(addr
));
485 T_ASSERT_POSIX_FAILURE(result
, ETIMEDOUT
, "vsock connect timeout");
488 T_DECL(connect_non_blocking
, "vsock connect non-blocking")
490 int socket
= vsock_new_socket();
492 const uint32_t port
= 4321;
493 const uint32_t cid
= vsock_get_local_cid(socket
);
496 struct sockaddr_vm listen_addr
;
498 long result
= vsock_listen(cid
, port
, &listen_addr
, 10, &listen_socket
);
499 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen");
502 long arg
= fcntl(socket
, F_GETFL
, NULL
);
503 T_ASSERT_GT(arg
, -1L, "vsock get args");
505 result
= fcntl(socket
, F_SETFL
, arg
);
506 T_ASSERT_GT(arg
, -1L, "vsock set args");
509 struct sockaddr_vm addr
= (struct sockaddr_vm
) {
513 result
= connect(socket
, (struct sockaddr
*)&addr
, sizeof(addr
));
514 if (result
!= 0 && errno
!= EINPROGRESS
) {
515 T_ASSERT_FAIL("vsock connect should succeed or return EINPROGRESS. errno: %u", errno
);
519 vsock_close(listen_socket
);
524 T_DECL(shutdown_not_connected
, "vsock shutdown - not connected")
526 int how
[] = {SHUT_RD
, SHUT_WR
, SHUT_RDWR
};
527 for (unsigned long i
= 0; i
< COUNT_ELEMS(how
); i
++) {
528 int socket
= vsock_new_socket();
529 int result
= shutdown(socket
, how
[i
]);
530 T_ASSERT_POSIX_FAILURE(result
, ENOTCONN
, "vsock cannot shutdown");
534 T_DECL(shutdown_reads
, "vsock shutdown - reads")
536 int socketA
, socketB
;
537 vsock_connect_peers(VMADDR_CID_ANY
, 8989, 10, &socketA
, &socketB
);
539 char *msg
= "This is test message.\n";
541 // 'A' sends a message.
542 vsock_send(socketA
, msg
);
544 // 'B' shutsdown reads.
545 int result
= shutdown(socketB
, SHUT_RD
);
546 T_ASSERT_POSIX_SUCCESS(result
, "vsock shutdown reads");
548 // 'B' reads nothing.
549 char buffer
[1024] = {0};
550 ssize_t read_bytes
= read(socketB
, buffer
, 1024);
551 T_ASSERT_EQ_LONG(0L, read_bytes
, "read zero bytes");
553 // 'B' can still send.
554 vsock_send(socketB
, msg
);
556 vsock_close(socketA
);
557 vsock_close(socketB
);
560 T_DECL(shutdown_writes
, "vsock shutdown - writes")
562 int socketA
, socketB
;
563 vsock_connect_peers(VMADDR_CID_ANY
, 8787, 10, &socketA
, &socketB
);
565 char *msg
= "This is test message.\n";
567 // 'A' sends a message.
568 vsock_send(socketA
, msg
);
570 // 'B' sends a message.
571 vsock_send(socketB
, msg
);
573 // send() hits us with a SIGPIPE if peer closes. ignore this and catch the error code.
574 vsock_disable_sigpipe(socketB
);
576 // 'B' shutsdown writes.
577 int result
= shutdown(socketB
, SHUT_WR
);
578 T_ASSERT_POSIX_SUCCESS(result
, "vsock shutdown writes");
580 // 'B' fails to write.
581 ssize_t sent_bytes
= send(socketB
, msg
, strlen(msg
), 0);
582 T_ASSERT_POSIX_FAILURE(sent_bytes
, EPIPE
, "vsock cannot write");
584 // 'B' can still read.
585 char buffer
[1024] = {0};
586 ssize_t read_bytes
= read(socketB
, buffer
, 1024);
587 T_ASSERT_EQ_LONG(strlen(msg
), (unsigned long)read_bytes
, "read all bytes");
589 vsock_close(socketA
);
590 vsock_close(socketB
);
593 T_DECL(shutdown_both
, "vsock shutdown - both")
595 int socketA
, socketB
;
596 vsock_connect_peers(VMADDR_CID_ANY
, 8686, 10, &socketA
, &socketB
);
598 char *msg
= "This is test message.\n";
599 char buffer
[1024] = {0};
601 // 'A' sends a message.
602 vsock_send(socketA
, msg
);
604 // 'B' sends a message.
605 vsock_send(socketB
, msg
);
607 // 'B' reads a message.
608 ssize_t read_bytes
= read(socketB
, buffer
, 1024);
609 T_ASSERT_EQ_LONG(strlen(msg
), (unsigned long)read_bytes
, "read all bytes");
610 T_ASSERT_EQ_STR(msg
, buffer
, "same message");
612 // 'A' sends a message.
613 vsock_send(socketA
, msg
);
615 // send() hits us with a SIGPIPE if peer closes. ignore this and catch the error code.
616 vsock_disable_sigpipe(socketB
);
618 // 'B' shutsdown reads and writes.
619 int result
= shutdown(socketB
, SHUT_RDWR
);
620 T_ASSERT_POSIX_SUCCESS(result
, "vsock shutdown reads and writes");
622 // 'B' fails to write.
623 ssize_t sent_bytes
= send(socketB
, msg
, strlen(msg
), 0);
624 T_ASSERT_POSIX_FAILURE(sent_bytes
, EPIPE
, "vsock cannot write");
626 // 'B' reads nothing.
627 read_bytes
= read(socketB
, buffer
, 1024);
628 T_ASSERT_EQ_LONG(0L, read_bytes
, "read zero bytes");
630 vsock_close(socketA
);
631 vsock_close(socketB
);
636 T_DECL(talk_self
, "vsock talk to self")
638 int socketA
, socketB
;
639 vsock_connect_peers(VMADDR_CID_ANY
, 4545, 10, &socketA
, &socketB
);
641 char buffer
[1024] = {0};
643 for (int i
= 0; i
< 64; i
++) {
645 char *msg
= (char*)malloc(64 * sizeof(char));
646 sprintf(msg
, "This is test message %d\n", i
);
647 vsock_send(socketA
, msg
);
649 // Receive a message.
650 ssize_t read_bytes
= read(socketB
, buffer
, 1024);
651 T_ASSERT_EQ_LONG(strlen(msg
), (unsigned long)read_bytes
, "read all bytes");
652 T_ASSERT_EQ_STR(msg
, buffer
, "same message");
656 vsock_close(socketA
);
657 vsock_close(socketB
);
660 T_DECL(talk_self_double
, "vsock talk to self - double sends")
662 int socketA
, socketB
;
663 vsock_connect_peers(VMADDR_CID_ANY
, 4646, 10, &socketA
, &socketB
);
665 char buffer
[1024] = {0};
667 for (int i
= 0; i
< 64; i
++) {
669 char *msg
= (char*)malloc(64 * sizeof(char));
670 sprintf(msg
, "This is test message %d\n", i
);
671 vsock_send(socketA
, msg
);
673 // Send the same message.
674 vsock_send(socketA
, msg
);
676 // Receive a message.
677 ssize_t read_bytes
= read(socketB
, buffer
, 1024);
678 T_ASSERT_EQ_LONG(strlen(msg
) * 2, (unsigned long)read_bytes
, "read all bytes");
679 char *expected_msg
= (char*)malloc(64 * sizeof(char));
680 sprintf(expected_msg
, "%s%s", msg
, msg
);
681 T_ASSERT_EQ_STR(expected_msg
, buffer
, "same message");
686 vsock_close(socketA
);
687 vsock_close(socketB
);
690 T_DECL(talk_self_early_close
, "vsock talk to self - peer closes early")
692 int socketA
, socketB
;
693 vsock_connect_peers(VMADDR_CID_ANY
, 4646, 10, &socketA
, &socketB
);
695 char *msg
= "This is a message.";
696 vsock_send(socketA
, msg
);
698 // send() hits us with a SIGPIPE if peer closes. ignore this and catch the error code.
699 vsock_disable_sigpipe(socketA
);
701 vsock_close(socketB
);
703 ssize_t result
= send(socketA
, msg
, strlen(msg
), 0);
704 T_ASSERT_POSIX_FAILURE(result
, EPIPE
, "vsock peer closed");
706 vsock_close(socketA
);
709 T_DECL(talk_self_connections
, "vsock talk to self - too many connections")
711 const uint32_t port
= 4747;
712 const int backlog
= 1;
714 struct sockaddr_vm listen_addr
;
716 int result
= vsock_listen(VMADDR_CID_ANY
, port
, &listen_addr
, backlog
, &listen_socket
);
717 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen");
719 const uint32_t connection_cid
= vsock_get_local_cid(listen_socket
);
722 int connected_socket
= vsock_new_socket();
723 struct sockaddr_vm addr
= (struct sockaddr_vm
) {
724 .svm_cid
= connection_cid
,
727 result
= connect(connected_socket
, (struct sockaddr
*)&addr
, sizeof(addr
));
728 T_ASSERT_POSIX_SUCCESS(result
, "vsock connection successful");
730 int bad_socket
= vsock_new_socket();
731 result
= connect(bad_socket
, (struct sockaddr
*)&addr
, sizeof(addr
));
732 T_ASSERT_POSIX_FAILURE(result
, ECONNREFUSED
, "vsock connection refused");
734 vsock_close(connected_socket
);
735 vsock_close(listen_socket
);
740 static const char* pcblist
= "net.vsock.pcblist";
742 T_DECL(vsock_pcblist_simple
, "vsock pcblist sysctl - simple")
744 // Create some socket to discover in the pcblist.
745 struct sockaddr_vm addr
;
747 int result
= vsock_listen(VMADDR_CID_ANY
, 88899, &addr
, 10, &socket
);
748 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen on a port");
750 // Get the buffer length for the pcblist.
752 result
= sysctlbyname(pcblist
, 0, &length
, 0, 0);
753 if (result
== ENOENT
) {
754 T_SKIP("%s missing", pcblist
);
756 T_ASSERT_POSIX_SUCCESS(result
, "vsock pcblist get buffer size (result %d)", result
);
758 // Allocate the buffer.
759 struct xvsockpgen
*buffer
= malloc(length
);
760 T_ASSERT_NOTNULL(buffer
, "allocated buffer is not null");
762 // Populate the buffer with the pcblist.
763 result
= sysctlbyname(pcblist
, buffer
, &length
, 0, 0);
764 T_ASSERT_POSIX_SUCCESS(result
, "vsock pcblist populate buffer");
766 // The socket should exist in the list.
767 bool exists
= vsock_address_exists(buffer
, addr
);
768 T_ASSERT_TRUE(exists
, "vsock pcblist contains the specified socket");
774 T_DECL(vsock_pcblist_added
, "vsock pcblist sysctl - socket added")
776 // Get the buffer length for the pcblist.
778 int result
= sysctlbyname(pcblist
, 0, &length
, 0, 0);
779 if (result
== ENOENT
) {
780 T_SKIP("%s missing", pcblist
);
782 T_ASSERT_POSIX_SUCCESS(result
, "vsock pcblist get buffer size (result %d)", result
);
784 // Create some socket to discover in the pcblist after making the first sysctl.
785 struct sockaddr_vm addr
;
787 result
= vsock_listen(VMADDR_CID_ANY
, 77799, &addr
, 10, &socket
);
788 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen on a port");
790 // Allocate the buffer.
791 struct xvsockpgen
*buffer
= malloc(length
);
792 T_ASSERT_NOTNULL(buffer
, "allocated buffer is not null");
794 // Populate the buffer with the pcblist.
795 result
= sysctlbyname(pcblist
, buffer
, &length
, 0, 0);
796 T_ASSERT_POSIX_SUCCESS(result
, "vsock pcblist populate buffer");
798 // The socket was created after the buffer and cannot fit.
799 bool exists
= vsock_address_exists(buffer
, addr
);
800 T_ASSERT_FALSE(exists
, "vsock pcblist should not contain the new socket");
806 T_DECL(vsock_pcblist_removed
, "vsock pcblist sysctl - socket removed")
808 // Create some socket to be removed after making the first sysctl.
809 struct sockaddr_vm addr
;
811 int result
= vsock_listen(VMADDR_CID_ANY
, 66699, &addr
, 10, &socket
);
812 T_ASSERT_POSIX_SUCCESS(result
, "vsock listen on a port");
814 // Get the buffer length for the pcblist.
816 result
= sysctlbyname(pcblist
, 0, &length
, 0, 0);
817 if (result
== ENOENT
) {
818 T_SKIP("%s missing", pcblist
);
820 T_ASSERT_POSIX_SUCCESS(result
, "vsock pcblist get buffer size (result %d)", result
);
822 // Close the socket early.
825 // Allocate the buffer.
826 struct xvsockpgen
*buffer
= malloc(length
);
827 T_ASSERT_NOTNULL(buffer
, "allocated buffer is not null");
829 // Populate the buffer with the pcblist.
830 result
= sysctlbyname(pcblist
, buffer
, &length
, 0, 0);
831 T_ASSERT_POSIX_SUCCESS(result
, "vsock pcblist populate buffer");
833 // The socket was destroyed before populating the list and should not exist.
834 bool exists
= vsock_address_exists(buffer
, addr
);
835 T_ASSERT_FALSE(exists
, "vsock pcblist should not contain the deleted socket");