xref: /xnu-12377.41.6/tests/vsock.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1*bbb1b6f9SApple OSS Distributions /*
2*bbb1b6f9SApple OSS Distributions  * Copyright (c) 2020 Apple Inc. All rights reserved.
3*bbb1b6f9SApple OSS Distributions  *
4*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*bbb1b6f9SApple OSS Distributions  *
6*bbb1b6f9SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*bbb1b6f9SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*bbb1b6f9SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*bbb1b6f9SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*bbb1b6f9SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*bbb1b6f9SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*bbb1b6f9SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*bbb1b6f9SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*bbb1b6f9SApple OSS Distributions  *
15*bbb1b6f9SApple OSS Distributions  * Please obtain a copy of the License at
16*bbb1b6f9SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*bbb1b6f9SApple OSS Distributions  *
18*bbb1b6f9SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*bbb1b6f9SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*bbb1b6f9SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*bbb1b6f9SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*bbb1b6f9SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*bbb1b6f9SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*bbb1b6f9SApple OSS Distributions  * limitations under the License.
25*bbb1b6f9SApple OSS Distributions  *
26*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*bbb1b6f9SApple OSS Distributions  */
28*bbb1b6f9SApple OSS Distributions 
29*bbb1b6f9SApple OSS Distributions #include <vsock_helpers.h>
30*bbb1b6f9SApple OSS Distributions 
31*bbb1b6f9SApple OSS Distributions T_GLOBAL_META(
32*bbb1b6f9SApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true),
33*bbb1b6f9SApple OSS Distributions 	T_META_NAMESPACE("xnu.vsock")
34*bbb1b6f9SApple OSS Distributions 	);
35*bbb1b6f9SApple OSS Distributions 
36*bbb1b6f9SApple OSS Distributions /* New Socket */
37*bbb1b6f9SApple OSS Distributions 
38*bbb1b6f9SApple OSS Distributions T_DECL(new_socket_getsockname, "vsock new - getsockname")
39*bbb1b6f9SApple OSS Distributions {
40*bbb1b6f9SApple OSS Distributions 	int socket = vsock_new_socket();
41*bbb1b6f9SApple OSS Distributions 
42*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
43*bbb1b6f9SApple OSS Distributions 	socklen_t length = sizeof(struct sockaddr_vm);
44*bbb1b6f9SApple OSS Distributions 	int result = getsockname(socket, (struct sockaddr *)&addr, &length);
45*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock getsockname");
46*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_INT(addr.svm_port, VMADDR_PORT_ANY, "name is any port");
47*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_INT(addr.svm_cid, VMADDR_CID_ANY, "name is any cid");
48*bbb1b6f9SApple OSS Distributions }
49*bbb1b6f9SApple OSS Distributions 
50*bbb1b6f9SApple OSS Distributions T_DECL(new_socket_getpeername, "vsock new - getpeername")
51*bbb1b6f9SApple OSS Distributions {
52*bbb1b6f9SApple OSS Distributions 	int socket = vsock_new_socket();
53*bbb1b6f9SApple OSS Distributions 
54*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
55*bbb1b6f9SApple OSS Distributions 	socklen_t length = sizeof(struct sockaddr_vm);
56*bbb1b6f9SApple OSS Distributions 	int result = getpeername(socket, (struct sockaddr *)&addr, &length);
57*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, ENOTCONN, "vsock getpeername");
58*bbb1b6f9SApple OSS Distributions }
59*bbb1b6f9SApple OSS Distributions 
60*bbb1b6f9SApple OSS Distributions /* Ioctl */
61*bbb1b6f9SApple OSS Distributions 
62*bbb1b6f9SApple OSS Distributions T_DECL(ioctl_cid, "vsock ioctl cid")
63*bbb1b6f9SApple OSS Distributions {
64*bbb1b6f9SApple OSS Distributions 	int socket = vsock_new_socket();
65*bbb1b6f9SApple OSS Distributions 	vsock_get_local_cid(socket);
66*bbb1b6f9SApple OSS Distributions }
67*bbb1b6f9SApple OSS Distributions 
68*bbb1b6f9SApple OSS Distributions /* Socketpair */
69*bbb1b6f9SApple OSS Distributions 
70*bbb1b6f9SApple OSS Distributions T_DECL(socketpair, "vsock socketpair")
71*bbb1b6f9SApple OSS Distributions {
72*bbb1b6f9SApple OSS Distributions 	int pair[2];
73*bbb1b6f9SApple OSS Distributions 	int error = socketpair(AF_VSOCK, SOCK_STREAM, 0, pair);
74*bbb1b6f9SApple OSS Distributions 	if (error < 0 && errno == ENODEV) {
75*bbb1b6f9SApple OSS Distributions 		T_SKIP("no vsock transport available");
76*bbb1b6f9SApple OSS Distributions 	}
77*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(error, EOPNOTSUPP, "vsock socketpair not supported");
78*bbb1b6f9SApple OSS Distributions }
79*bbb1b6f9SApple OSS Distributions 
80*bbb1b6f9SApple OSS Distributions /* Bind */
81*bbb1b6f9SApple OSS Distributions 
82*bbb1b6f9SApple OSS Distributions T_DECL(bind, "vsock bind to specific port")
83*bbb1b6f9SApple OSS Distributions {
84*bbb1b6f9SApple OSS Distributions 	int socket;
85*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
86*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
87*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_ANY, port, &addr, &socket);
88*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to specific port");
89*bbb1b6f9SApple OSS Distributions }
90*bbb1b6f9SApple OSS Distributions 
91*bbb1b6f9SApple OSS Distributions T_DECL(bind_any, "vsock bind to any port")
92*bbb1b6f9SApple OSS Distributions {
93*bbb1b6f9SApple OSS Distributions 	int socket;
94*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
95*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_ANY, VMADDR_PORT_ANY, &addr, &socket);
96*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to any port");
97*bbb1b6f9SApple OSS Distributions }
98*bbb1b6f9SApple OSS Distributions 
99*bbb1b6f9SApple OSS Distributions T_DECL(bind_getsockname, "vsock bind - getsockname")
100*bbb1b6f9SApple OSS Distributions {
101*bbb1b6f9SApple OSS Distributions 	int socket;
102*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
103*bbb1b6f9SApple OSS Distributions 	const uint32_t port = VMADDR_PORT_ANY;
104*bbb1b6f9SApple OSS Distributions 	const uint32_t cid = VMADDR_CID_ANY;
105*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(cid, port, &addr, &socket);
106*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to any port");
107*bbb1b6f9SApple OSS Distributions 
108*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm bound_addr = vsock_getsockname(socket);
109*bbb1b6f9SApple OSS Distributions 	T_ASSERT_NE_INT(bound_addr.svm_port, port, "bound to unique local port");
110*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_INT(bound_addr.svm_cid, cid, "bound to any cid");
111*bbb1b6f9SApple OSS Distributions }
112*bbb1b6f9SApple OSS Distributions 
113*bbb1b6f9SApple OSS Distributions T_DECL(bind_hypervisor, "vsock do not bind to hypervisor cid")
114*bbb1b6f9SApple OSS Distributions {
115*bbb1b6f9SApple OSS Distributions 	int socket;
116*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
117*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_HYPERVISOR, VMADDR_PORT_ANY, &addr, &socket);
118*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EADDRNOTAVAIL, "vsock do not bind to hypervisor cid");
119*bbb1b6f9SApple OSS Distributions }
120*bbb1b6f9SApple OSS Distributions 
121*bbb1b6f9SApple OSS Distributions T_DECL(bind_reserved, "vsock do not bind to reserved cid")
122*bbb1b6f9SApple OSS Distributions {
123*bbb1b6f9SApple OSS Distributions 	int socket;
124*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
125*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_RESERVED, VMADDR_PORT_ANY, &addr, &socket);
126*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EADDRNOTAVAIL, "vsock do not bind to reserved cid");
127*bbb1b6f9SApple OSS Distributions }
128*bbb1b6f9SApple OSS Distributions 
129*bbb1b6f9SApple OSS Distributions T_DECL(bind_host, "vsock do not bind to host cid")
130*bbb1b6f9SApple OSS Distributions {
131*bbb1b6f9SApple OSS Distributions 	int socket;
132*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
133*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_HOST, VMADDR_PORT_ANY, &addr, &socket);
134*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EADDRNOTAVAIL, "vsock do not bind to host cid");
135*bbb1b6f9SApple OSS Distributions }
136*bbb1b6f9SApple OSS Distributions 
137*bbb1b6f9SApple OSS Distributions T_DECL(bind_zero, "vsock bind to port zero", T_META_ASROOT(true))
138*bbb1b6f9SApple OSS Distributions {
139*bbb1b6f9SApple OSS Distributions 	const uint32_t port = 0;
140*bbb1b6f9SApple OSS Distributions 
141*bbb1b6f9SApple OSS Distributions 	int socket;
142*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
143*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_ANY, port, &addr, &socket);
144*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to port zero");
145*bbb1b6f9SApple OSS Distributions 
146*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm bound_addr;
147*bbb1b6f9SApple OSS Distributions 	socklen_t length = sizeof(struct sockaddr_vm);
148*bbb1b6f9SApple OSS Distributions 	result = getsockname(socket, (struct sockaddr *)&bound_addr, &length);
149*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock getsockname");
150*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_INT((int) sizeof(bound_addr), length, "correct address length");
151*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_UINT(bound_addr.svm_port, port, "bound to local port zero");
152*bbb1b6f9SApple OSS Distributions }
153*bbb1b6f9SApple OSS Distributions 
154*bbb1b6f9SApple OSS Distributions T_DECL(bind_double, "vsock double bind")
155*bbb1b6f9SApple OSS Distributions {
156*bbb1b6f9SApple OSS Distributions 	const uint32_t cid = VMADDR_CID_ANY;
157*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
158*bbb1b6f9SApple OSS Distributions 
159*bbb1b6f9SApple OSS Distributions 	int socket;
160*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
161*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(cid, port, &addr, &socket);
162*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to a port");
163*bbb1b6f9SApple OSS Distributions 
164*bbb1b6f9SApple OSS Distributions 	result = bind(socket, (struct sockaddr *) &addr, sizeof(addr));
165*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EINVAL, "vsock bind to same port");
166*bbb1b6f9SApple OSS Distributions }
167*bbb1b6f9SApple OSS Distributions 
168*bbb1b6f9SApple OSS Distributions T_DECL(bind_same, "vsock bind same address and port")
169*bbb1b6f9SApple OSS Distributions {
170*bbb1b6f9SApple OSS Distributions 	const uint32_t cid = VMADDR_CID_ANY;
171*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
172*bbb1b6f9SApple OSS Distributions 
173*bbb1b6f9SApple OSS Distributions 	int socket;
174*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
175*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(cid, port, &addr, &socket);
176*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to a port");
177*bbb1b6f9SApple OSS Distributions 
178*bbb1b6f9SApple OSS Distributions 	result = vsock_bind(cid, port, &addr, &socket);
179*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EADDRINUSE, "vsock bind to same address and port");
180*bbb1b6f9SApple OSS Distributions }
181*bbb1b6f9SApple OSS Distributions 
182*bbb1b6f9SApple OSS Distributions T_DECL(bind_port_reuse, "vsock bind port reuse")
183*bbb1b6f9SApple OSS Distributions {
184*bbb1b6f9SApple OSS Distributions 	const uint32_t cid = VMADDR_CID_ANY;
185*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
186*bbb1b6f9SApple OSS Distributions 
187*bbb1b6f9SApple OSS Distributions 	int socket;
188*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
189*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(cid, port, &addr, &socket);
190*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to a port");
191*bbb1b6f9SApple OSS Distributions 
192*bbb1b6f9SApple OSS Distributions 	vsock_close(socket);
193*bbb1b6f9SApple OSS Distributions 
194*bbb1b6f9SApple OSS Distributions 	result = vsock_bind(cid, port, &addr, &socket);
195*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind to a port");
196*bbb1b6f9SApple OSS Distributions }
197*bbb1b6f9SApple OSS Distributions 
198*bbb1b6f9SApple OSS Distributions T_DECL(bind_privileged_non_root, "vsock bind on privileged port - non-root", T_META_ASROOT(false))
199*bbb1b6f9SApple OSS Distributions {
200*bbb1b6f9SApple OSS Distributions 	if (geteuid() == 0) {
201*bbb1b6f9SApple OSS Distributions 		T_SKIP("test requires non-root privileges to run.");
202*bbb1b6f9SApple OSS Distributions 	}
203*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
204*bbb1b6f9SApple OSS Distributions 	int socket;
205*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_ANY, 5, &addr, &socket);
206*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EACCES, "vsock bind privileged as non-root");
207*bbb1b6f9SApple OSS Distributions }
208*bbb1b6f9SApple OSS Distributions 
209*bbb1b6f9SApple OSS Distributions T_DECL(bind_privileged_root, "vsock bind on privileged port - root", T_META_ASROOT(true))
210*bbb1b6f9SApple OSS Distributions {
211*bbb1b6f9SApple OSS Distributions 	if (geteuid() != 0) {
212*bbb1b6f9SApple OSS Distributions 		T_SKIP("test requires root privileges to run.");
213*bbb1b6f9SApple OSS Distributions 	}
214*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
215*bbb1b6f9SApple OSS Distributions 	int socket;
216*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind(VMADDR_CID_ANY, 6, &addr, &socket);
217*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind privileged as root");
218*bbb1b6f9SApple OSS Distributions }
219*bbb1b6f9SApple OSS Distributions 
220*bbb1b6f9SApple OSS Distributions T_DECL(bind_no_family, "vsock bind with unspecified family")
221*bbb1b6f9SApple OSS Distributions {
222*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind_family(AF_UNSPEC);
223*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind with unspecified family");
224*bbb1b6f9SApple OSS Distributions }
225*bbb1b6f9SApple OSS Distributions 
226*bbb1b6f9SApple OSS Distributions T_DECL(bind_vsock_family, "vsock bind with vsock family")
227*bbb1b6f9SApple OSS Distributions {
228*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind_family(AF_VSOCK);
229*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock bind with vsock family");
230*bbb1b6f9SApple OSS Distributions }
231*bbb1b6f9SApple OSS Distributions 
232*bbb1b6f9SApple OSS Distributions T_DECL(bind_wrong_family, "vsock bind with wrong family")
233*bbb1b6f9SApple OSS Distributions {
234*bbb1b6f9SApple OSS Distributions 	int result = vsock_bind_family(AF_INET);
235*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EAFNOSUPPORT, "vsock bind with wrong family");
236*bbb1b6f9SApple OSS Distributions }
237*bbb1b6f9SApple OSS Distributions 
238*bbb1b6f9SApple OSS Distributions /* Listen */
239*bbb1b6f9SApple OSS Distributions 
240*bbb1b6f9SApple OSS Distributions T_DECL(listen, "vsock listen on specific port")
241*bbb1b6f9SApple OSS Distributions {
242*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
243*bbb1b6f9SApple OSS Distributions 	int socket;
244*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
245*bbb1b6f9SApple OSS Distributions 	int result = vsock_listen(VMADDR_CID_ANY, port, &addr, 10, &socket);
246*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock listen");
247*bbb1b6f9SApple OSS Distributions }
248*bbb1b6f9SApple OSS Distributions 
249*bbb1b6f9SApple OSS Distributions T_DECL(listen_any, "vsock listen on any port")
250*bbb1b6f9SApple OSS Distributions {
251*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
252*bbb1b6f9SApple OSS Distributions 	int socket;
253*bbb1b6f9SApple OSS Distributions 	int result = vsock_listen(VMADDR_CID_ANY, VMADDR_PORT_ANY, &addr, 10, &socket);
254*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock listen");
255*bbb1b6f9SApple OSS Distributions }
256*bbb1b6f9SApple OSS Distributions 
257*bbb1b6f9SApple OSS Distributions /* Connect */
258*bbb1b6f9SApple OSS Distributions 
259*bbb1b6f9SApple OSS Distributions T_DECL(connect_non_hypervisor, "vsock connect to remote other than hypervisor")
260*bbb1b6f9SApple OSS Distributions {
261*bbb1b6f9SApple OSS Distributions 	int socket;
262*bbb1b6f9SApple OSS Distributions 	int result = vsock_connect(5555, 1234, &socket);
263*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EFAULT, "vsock connect non-hypervisor");
264*bbb1b6f9SApple OSS Distributions }
265*bbb1b6f9SApple OSS Distributions 
266*bbb1b6f9SApple OSS Distributions T_DECL(connect_non_listening_host, "vsock connect to non-listening host port")
267*bbb1b6f9SApple OSS Distributions {
268*bbb1b6f9SApple OSS Distributions 	int socket;
269*bbb1b6f9SApple OSS Distributions 	int result = vsock_connect(VMADDR_CID_HOST, 7777, &socket);
270*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EAGAIN, "vsock connect non-listening host port");
271*bbb1b6f9SApple OSS Distributions }
272*bbb1b6f9SApple OSS Distributions 
273*bbb1b6f9SApple OSS Distributions T_DECL(connect_non_listening_hypervisor, "vsock connect to non-listening hypervisor port")
274*bbb1b6f9SApple OSS Distributions {
275*bbb1b6f9SApple OSS Distributions 	int socket;
276*bbb1b6f9SApple OSS Distributions 	int result = vsock_connect(VMADDR_CID_HYPERVISOR, 4444, &socket);
277*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EAGAIN, "vsock connect non-listening hypervisor port");
278*bbb1b6f9SApple OSS Distributions }
279*bbb1b6f9SApple OSS Distributions 
280*bbb1b6f9SApple OSS Distributions T_DECL(connect_getsockname, "vsock connect - getsockname")
281*bbb1b6f9SApple OSS Distributions {
282*bbb1b6f9SApple OSS Distributions 	int socket;
283*bbb1b6f9SApple OSS Distributions 	int result = vsock_connect(VMADDR_CID_HOST, 9999, &socket);
284*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EAGAIN, "vsock connect non-listening");
285*bbb1b6f9SApple OSS Distributions 
286*bbb1b6f9SApple OSS Distributions 	vsock_getsockname(socket);
287*bbb1b6f9SApple OSS Distributions }
288*bbb1b6f9SApple OSS Distributions 
289*bbb1b6f9SApple OSS Distributions T_DECL(connect_timeout, "vsock connect with timeout")
290*bbb1b6f9SApple OSS Distributions {
291*bbb1b6f9SApple OSS Distributions 	int socket = vsock_new_socket();
292*bbb1b6f9SApple OSS Distributions 
293*bbb1b6f9SApple OSS Distributions 	struct timeval timeout = (struct timeval) {
294*bbb1b6f9SApple OSS Distributions 		.tv_sec = 0,
295*bbb1b6f9SApple OSS Distributions 		.tv_usec = 1,
296*bbb1b6f9SApple OSS Distributions 	};
297*bbb1b6f9SApple OSS Distributions 	int result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
298*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock set socket timeout");
299*bbb1b6f9SApple OSS Distributions 
300*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
301*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr = (struct sockaddr_vm) {
302*bbb1b6f9SApple OSS Distributions 		.svm_cid = VMADDR_CID_HOST,
303*bbb1b6f9SApple OSS Distributions 		.svm_port = port,
304*bbb1b6f9SApple OSS Distributions 	};
305*bbb1b6f9SApple OSS Distributions 	result = connect(socket, (struct sockaddr *)&addr, sizeof(addr));
306*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, ETIMEDOUT, "vsock connect timeout");
307*bbb1b6f9SApple OSS Distributions }
308*bbb1b6f9SApple OSS Distributions 
309*bbb1b6f9SApple OSS Distributions T_DECL(connect_non_blocking, "vsock connect non-blocking")
310*bbb1b6f9SApple OSS Distributions {
311*bbb1b6f9SApple OSS Distributions 	int socket = vsock_new_socket();
312*bbb1b6f9SApple OSS Distributions 
313*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
314*bbb1b6f9SApple OSS Distributions 	const uint32_t cid = vsock_get_local_cid(socket);
315*bbb1b6f9SApple OSS Distributions 
316*bbb1b6f9SApple OSS Distributions 	// Listen.
317*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm listen_addr;
318*bbb1b6f9SApple OSS Distributions 	int listen_socket;
319*bbb1b6f9SApple OSS Distributions 	long result = vsock_listen(cid, port, &listen_addr, 10, &listen_socket);
320*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock listen");
321*bbb1b6f9SApple OSS Distributions 
322*bbb1b6f9SApple OSS Distributions 	// Set non-blocking.
323*bbb1b6f9SApple OSS Distributions 	long arg = fcntl(socket, F_GETFL, NULL);
324*bbb1b6f9SApple OSS Distributions 	T_ASSERT_GT(arg, -1L, "vsock get args");
325*bbb1b6f9SApple OSS Distributions 	arg |= O_NONBLOCK;
326*bbb1b6f9SApple OSS Distributions 	result = fcntl(socket, F_SETFL, arg);
327*bbb1b6f9SApple OSS Distributions 	T_ASSERT_GT(arg, -1L, "vsock set args");
328*bbb1b6f9SApple OSS Distributions 
329*bbb1b6f9SApple OSS Distributions 	// Connect.
330*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr = (struct sockaddr_vm) {
331*bbb1b6f9SApple OSS Distributions 		.svm_cid = cid,
332*bbb1b6f9SApple OSS Distributions 		.svm_port = port,
333*bbb1b6f9SApple OSS Distributions 	};
334*bbb1b6f9SApple OSS Distributions 	result = connect(socket, (struct sockaddr *)&addr, sizeof(addr));
335*bbb1b6f9SApple OSS Distributions 	if (result != 0 && errno != EINPROGRESS) {
336*bbb1b6f9SApple OSS Distributions 		T_ASSERT_FAIL("vsock connect should succeed or return EINPROGRESS. errno: %u", errno);
337*bbb1b6f9SApple OSS Distributions 	}
338*bbb1b6f9SApple OSS Distributions 
339*bbb1b6f9SApple OSS Distributions 	vsock_close(socket);
340*bbb1b6f9SApple OSS Distributions 	vsock_close(listen_socket);
341*bbb1b6f9SApple OSS Distributions }
342*bbb1b6f9SApple OSS Distributions 
343*bbb1b6f9SApple OSS Distributions /* Shutdown */
344*bbb1b6f9SApple OSS Distributions 
345*bbb1b6f9SApple OSS Distributions T_DECL(shutdown_not_connected, "vsock shutdown - not connected")
346*bbb1b6f9SApple OSS Distributions {
347*bbb1b6f9SApple OSS Distributions 	int how[] = {SHUT_RD, SHUT_WR, SHUT_RDWR};
348*bbb1b6f9SApple OSS Distributions 	for (unsigned long i = 0; i < COUNT_ELEMS(how); i++) {
349*bbb1b6f9SApple OSS Distributions 		int socket = vsock_new_socket();
350*bbb1b6f9SApple OSS Distributions 		int result = shutdown(socket, how[i]);
351*bbb1b6f9SApple OSS Distributions 		T_ASSERT_POSIX_FAILURE(result, ENOTCONN, "vsock cannot shutdown");
352*bbb1b6f9SApple OSS Distributions 	}
353*bbb1b6f9SApple OSS Distributions }
354*bbb1b6f9SApple OSS Distributions 
355*bbb1b6f9SApple OSS Distributions T_DECL(shutdown_reads, "vsock shutdown - reads")
356*bbb1b6f9SApple OSS Distributions {
357*bbb1b6f9SApple OSS Distributions 	int socketA, socketB;
358*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
359*bbb1b6f9SApple OSS Distributions 	vsock_connect_peers(VMADDR_CID_ANY, port, 10, &socketA, &socketB);
360*bbb1b6f9SApple OSS Distributions 
361*bbb1b6f9SApple OSS Distributions 	char *msg = "This is test message.\n";
362*bbb1b6f9SApple OSS Distributions 
363*bbb1b6f9SApple OSS Distributions 	// 'A' sends a message.
364*bbb1b6f9SApple OSS Distributions 	vsock_send(socketA, msg);
365*bbb1b6f9SApple OSS Distributions 
366*bbb1b6f9SApple OSS Distributions 	// 'B' shutsdown reads.
367*bbb1b6f9SApple OSS Distributions 	int result = shutdown(socketB, SHUT_RD);
368*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock shutdown reads");
369*bbb1b6f9SApple OSS Distributions 
370*bbb1b6f9SApple OSS Distributions 	// 'B' reads nothing.
371*bbb1b6f9SApple OSS Distributions 	char buffer[1024] = {0};
372*bbb1b6f9SApple OSS Distributions 	ssize_t read_bytes = read(socketB, buffer, 1024);
373*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_LONG(0L, read_bytes, "read zero bytes");
374*bbb1b6f9SApple OSS Distributions 
375*bbb1b6f9SApple OSS Distributions 	// 'B' can still send.
376*bbb1b6f9SApple OSS Distributions 	vsock_send(socketB, msg);
377*bbb1b6f9SApple OSS Distributions 
378*bbb1b6f9SApple OSS Distributions 	vsock_close(socketA);
379*bbb1b6f9SApple OSS Distributions 	vsock_close(socketB);
380*bbb1b6f9SApple OSS Distributions }
381*bbb1b6f9SApple OSS Distributions 
382*bbb1b6f9SApple OSS Distributions T_DECL(shutdown_writes, "vsock shutdown - writes")
383*bbb1b6f9SApple OSS Distributions {
384*bbb1b6f9SApple OSS Distributions 	int socketA, socketB;
385*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
386*bbb1b6f9SApple OSS Distributions 	vsock_connect_peers(VMADDR_CID_ANY, port, 10, &socketA, &socketB);
387*bbb1b6f9SApple OSS Distributions 
388*bbb1b6f9SApple OSS Distributions 	char *msg = "This is test message.\n";
389*bbb1b6f9SApple OSS Distributions 
390*bbb1b6f9SApple OSS Distributions 	// 'A' sends a message.
391*bbb1b6f9SApple OSS Distributions 	vsock_send(socketA, msg);
392*bbb1b6f9SApple OSS Distributions 
393*bbb1b6f9SApple OSS Distributions 	// 'B' sends a message.
394*bbb1b6f9SApple OSS Distributions 	vsock_send(socketB, msg);
395*bbb1b6f9SApple OSS Distributions 
396*bbb1b6f9SApple OSS Distributions 	// send() hits us with a SIGPIPE if peer closes. ignore this and catch the error code.
397*bbb1b6f9SApple OSS Distributions 	vsock_disable_sigpipe(socketB);
398*bbb1b6f9SApple OSS Distributions 
399*bbb1b6f9SApple OSS Distributions 	// 'B' shutsdown writes.
400*bbb1b6f9SApple OSS Distributions 	int result = shutdown(socketB, SHUT_WR);
401*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock shutdown writes");
402*bbb1b6f9SApple OSS Distributions 
403*bbb1b6f9SApple OSS Distributions 	// 'B' fails to write.
404*bbb1b6f9SApple OSS Distributions 	ssize_t sent_bytes = send(socketB, msg, strlen(msg), 0);
405*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(sent_bytes, EPIPE, "vsock cannot write");
406*bbb1b6f9SApple OSS Distributions 
407*bbb1b6f9SApple OSS Distributions 	// 'B' can still read.
408*bbb1b6f9SApple OSS Distributions 	char buffer[1024] = {0};
409*bbb1b6f9SApple OSS Distributions 	ssize_t read_bytes = read(socketB, buffer, 1024);
410*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_LONG(strlen(msg), (unsigned long)read_bytes, "read all bytes");
411*bbb1b6f9SApple OSS Distributions 
412*bbb1b6f9SApple OSS Distributions 	vsock_close(socketA);
413*bbb1b6f9SApple OSS Distributions 	vsock_close(socketB);
414*bbb1b6f9SApple OSS Distributions }
415*bbb1b6f9SApple OSS Distributions 
416*bbb1b6f9SApple OSS Distributions T_DECL(shutdown_both, "vsock shutdown - both")
417*bbb1b6f9SApple OSS Distributions {
418*bbb1b6f9SApple OSS Distributions 	int socketA, socketB;
419*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
420*bbb1b6f9SApple OSS Distributions 	vsock_connect_peers(VMADDR_CID_ANY, port, 10, &socketA, &socketB);
421*bbb1b6f9SApple OSS Distributions 
422*bbb1b6f9SApple OSS Distributions 	char *msg = "This is test message.\n";
423*bbb1b6f9SApple OSS Distributions 	char buffer[1024] = {0};
424*bbb1b6f9SApple OSS Distributions 
425*bbb1b6f9SApple OSS Distributions 	// 'A' sends a message.
426*bbb1b6f9SApple OSS Distributions 	vsock_send(socketA, msg);
427*bbb1b6f9SApple OSS Distributions 
428*bbb1b6f9SApple OSS Distributions 	// 'B' sends a message.
429*bbb1b6f9SApple OSS Distributions 	vsock_send(socketB, msg);
430*bbb1b6f9SApple OSS Distributions 
431*bbb1b6f9SApple OSS Distributions 	// 'B' reads a message.
432*bbb1b6f9SApple OSS Distributions 	ssize_t read_bytes = read(socketB, buffer, 1024);
433*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_LONG(strlen(msg), (unsigned long)read_bytes, "read all bytes");
434*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_STR(msg, buffer, "same message");
435*bbb1b6f9SApple OSS Distributions 
436*bbb1b6f9SApple OSS Distributions 	// 'A' sends a message.
437*bbb1b6f9SApple OSS Distributions 	vsock_send(socketA, msg);
438*bbb1b6f9SApple OSS Distributions 
439*bbb1b6f9SApple OSS Distributions 	// send() hits us with a SIGPIPE if peer closes. ignore this and catch the error code.
440*bbb1b6f9SApple OSS Distributions 	vsock_disable_sigpipe(socketB);
441*bbb1b6f9SApple OSS Distributions 
442*bbb1b6f9SApple OSS Distributions 	// 'B' shutsdown reads and writes.
443*bbb1b6f9SApple OSS Distributions 	int result = shutdown(socketB, SHUT_RDWR);
444*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock shutdown reads and writes");
445*bbb1b6f9SApple OSS Distributions 
446*bbb1b6f9SApple OSS Distributions 	// 'B' fails to write.
447*bbb1b6f9SApple OSS Distributions 	ssize_t sent_bytes = send(socketB, msg, strlen(msg), 0);
448*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(sent_bytes, EPIPE, "vsock cannot write");
449*bbb1b6f9SApple OSS Distributions 
450*bbb1b6f9SApple OSS Distributions 	// 'B' reads nothing.
451*bbb1b6f9SApple OSS Distributions 	read_bytes = read(socketB, buffer, 1024);
452*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ_LONG(0L, read_bytes, "read zero bytes");
453*bbb1b6f9SApple OSS Distributions 
454*bbb1b6f9SApple OSS Distributions 	vsock_close(socketA);
455*bbb1b6f9SApple OSS Distributions 	vsock_close(socketB);
456*bbb1b6f9SApple OSS Distributions }
457*bbb1b6f9SApple OSS Distributions 
458*bbb1b6f9SApple OSS Distributions /* Communication */
459*bbb1b6f9SApple OSS Distributions 
460*bbb1b6f9SApple OSS Distributions T_DECL(talk_self, "vsock talk to self")
461*bbb1b6f9SApple OSS Distributions {
462*bbb1b6f9SApple OSS Distributions 	int socketA, socketB;
463*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
464*bbb1b6f9SApple OSS Distributions 	vsock_connect_peers(VMADDR_CID_ANY, port, 10, &socketA, &socketB);
465*bbb1b6f9SApple OSS Distributions 
466*bbb1b6f9SApple OSS Distributions 	char buffer[1024] = {0};
467*bbb1b6f9SApple OSS Distributions 
468*bbb1b6f9SApple OSS Distributions 	for (int i = 0; i < 64; i++) {
469*bbb1b6f9SApple OSS Distributions 		// Send a message.
470*bbb1b6f9SApple OSS Distributions 		char *msg = (char*)malloc(64 * sizeof(char));
471*bbb1b6f9SApple OSS Distributions 		sprintf(msg, "This is test message %d\n", i);
472*bbb1b6f9SApple OSS Distributions 		vsock_send(socketA, msg);
473*bbb1b6f9SApple OSS Distributions 
474*bbb1b6f9SApple OSS Distributions 		// Receive a message.
475*bbb1b6f9SApple OSS Distributions 		ssize_t read_bytes = read(socketB, buffer, 1024);
476*bbb1b6f9SApple OSS Distributions 		T_ASSERT_EQ_LONG(strlen(msg), (unsigned long)read_bytes, "read all bytes");
477*bbb1b6f9SApple OSS Distributions 		T_ASSERT_EQ_STR(msg, buffer, "same message");
478*bbb1b6f9SApple OSS Distributions 		free(msg);
479*bbb1b6f9SApple OSS Distributions 	}
480*bbb1b6f9SApple OSS Distributions 
481*bbb1b6f9SApple OSS Distributions 	vsock_close(socketA);
482*bbb1b6f9SApple OSS Distributions 	vsock_close(socketB);
483*bbb1b6f9SApple OSS Distributions }
484*bbb1b6f9SApple OSS Distributions 
485*bbb1b6f9SApple OSS Distributions T_DECL(talk_self_double, "vsock talk to self - double sends")
486*bbb1b6f9SApple OSS Distributions {
487*bbb1b6f9SApple OSS Distributions 	int socketA, socketB;
488*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
489*bbb1b6f9SApple OSS Distributions 	vsock_connect_peers(VMADDR_CID_ANY, port, 10, &socketA, &socketB);
490*bbb1b6f9SApple OSS Distributions 
491*bbb1b6f9SApple OSS Distributions 	char buffer[1024] = {0};
492*bbb1b6f9SApple OSS Distributions 
493*bbb1b6f9SApple OSS Distributions 	for (int i = 0; i < 64; i++) {
494*bbb1b6f9SApple OSS Distributions 		// Send a message.
495*bbb1b6f9SApple OSS Distributions 		char *msg = (char*)malloc(64 * sizeof(char));
496*bbb1b6f9SApple OSS Distributions 		sprintf(msg, "This is test message %d\n", i);
497*bbb1b6f9SApple OSS Distributions 		vsock_send(socketA, msg);
498*bbb1b6f9SApple OSS Distributions 
499*bbb1b6f9SApple OSS Distributions 		// Send the same message.
500*bbb1b6f9SApple OSS Distributions 		vsock_send(socketA, msg);
501*bbb1b6f9SApple OSS Distributions 
502*bbb1b6f9SApple OSS Distributions 		// Receive a message.
503*bbb1b6f9SApple OSS Distributions 		ssize_t read_bytes = read(socketB, buffer, 1024);
504*bbb1b6f9SApple OSS Distributions 		T_ASSERT_EQ_LONG(strlen(msg) * 2, (unsigned long)read_bytes, "read all bytes");
505*bbb1b6f9SApple OSS Distributions 		char *expected_msg = (char*)malloc(64 * sizeof(char));
506*bbb1b6f9SApple OSS Distributions 		sprintf(expected_msg, "%s%s", msg, msg);
507*bbb1b6f9SApple OSS Distributions 		T_ASSERT_EQ_STR(expected_msg, buffer, "same message");
508*bbb1b6f9SApple OSS Distributions 		free(msg);
509*bbb1b6f9SApple OSS Distributions 		free(expected_msg);
510*bbb1b6f9SApple OSS Distributions 	}
511*bbb1b6f9SApple OSS Distributions 
512*bbb1b6f9SApple OSS Distributions 	vsock_close(socketA);
513*bbb1b6f9SApple OSS Distributions 	vsock_close(socketB);
514*bbb1b6f9SApple OSS Distributions }
515*bbb1b6f9SApple OSS Distributions 
516*bbb1b6f9SApple OSS Distributions T_DECL(talk_self_early_close, "vsock talk to self - peer closes early")
517*bbb1b6f9SApple OSS Distributions {
518*bbb1b6f9SApple OSS Distributions 	int socketA, socketB;
519*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
520*bbb1b6f9SApple OSS Distributions 	vsock_connect_peers(VMADDR_CID_ANY, port, 10, &socketA, &socketB);
521*bbb1b6f9SApple OSS Distributions 
522*bbb1b6f9SApple OSS Distributions 	char *msg = "This is a message.";
523*bbb1b6f9SApple OSS Distributions 	vsock_send(socketA, msg);
524*bbb1b6f9SApple OSS Distributions 
525*bbb1b6f9SApple OSS Distributions 	// send() hits us with a SIGPIPE if peer closes. ignore this and catch the error code.
526*bbb1b6f9SApple OSS Distributions 	vsock_disable_sigpipe(socketA);
527*bbb1b6f9SApple OSS Distributions 
528*bbb1b6f9SApple OSS Distributions 	vsock_close(socketB);
529*bbb1b6f9SApple OSS Distributions 
530*bbb1b6f9SApple OSS Distributions 	ssize_t result = send(socketA, msg, strlen(msg), 0);
531*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EPIPE, "vsock peer closed");
532*bbb1b6f9SApple OSS Distributions 
533*bbb1b6f9SApple OSS Distributions 	vsock_close(socketA);
534*bbb1b6f9SApple OSS Distributions }
535*bbb1b6f9SApple OSS Distributions 
536*bbb1b6f9SApple OSS Distributions T_DECL(talk_self_connections, "vsock talk to self - too many connections")
537*bbb1b6f9SApple OSS Distributions {
538*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
539*bbb1b6f9SApple OSS Distributions 	const int backlog = 1;
540*bbb1b6f9SApple OSS Distributions 
541*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm listen_addr;
542*bbb1b6f9SApple OSS Distributions 	int listen_socket;
543*bbb1b6f9SApple OSS Distributions 	int result = vsock_listen(VMADDR_CID_ANY, port, &listen_addr, backlog, &listen_socket);
544*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock listen");
545*bbb1b6f9SApple OSS Distributions 
546*bbb1b6f9SApple OSS Distributions 	const uint32_t connection_cid = vsock_get_local_cid(listen_socket);
547*bbb1b6f9SApple OSS Distributions 
548*bbb1b6f9SApple OSS Distributions 	// One backlog.
549*bbb1b6f9SApple OSS Distributions 	int connected_socket = vsock_new_socket();
550*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr = (struct sockaddr_vm) {
551*bbb1b6f9SApple OSS Distributions 		.svm_cid = connection_cid,
552*bbb1b6f9SApple OSS Distributions 		.svm_port = port,
553*bbb1b6f9SApple OSS Distributions 	};
554*bbb1b6f9SApple OSS Distributions 	result = connect(connected_socket, (struct sockaddr *)&addr, sizeof(addr));
555*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock connection successful");
556*bbb1b6f9SApple OSS Distributions 
557*bbb1b6f9SApple OSS Distributions 	int bad_socket = vsock_new_socket();
558*bbb1b6f9SApple OSS Distributions 	result = connect(bad_socket, (struct sockaddr *)&addr, sizeof(addr));
559*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, ECONNREFUSED, "vsock connection refused");
560*bbb1b6f9SApple OSS Distributions 
561*bbb1b6f9SApple OSS Distributions 	vsock_close(connected_socket);
562*bbb1b6f9SApple OSS Distributions 	vsock_close(listen_socket);
563*bbb1b6f9SApple OSS Distributions }
564*bbb1b6f9SApple OSS Distributions 
565*bbb1b6f9SApple OSS Distributions // rdar://84098487 (SEED: Web: Virtio-socket sent data lost after 128KB)
566*bbb1b6f9SApple OSS Distributions T_DECL(talk_self_large_writes, "vsock talk to self with large writes")
567*bbb1b6f9SApple OSS Distributions {
568*bbb1b6f9SApple OSS Distributions 	int socketA, socketB;
569*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
570*bbb1b6f9SApple OSS Distributions 	vsock_connect_peers(VMADDR_CID_ANY, port, 10, &socketA, &socketB);
571*bbb1b6f9SApple OSS Distributions 
572*bbb1b6f9SApple OSS Distributions 	size_t size = 65536 * 4;
573*bbb1b6f9SApple OSS Distributions 	char buffer[65536 * 4] = {0};
574*bbb1b6f9SApple OSS Distributions 	void *random = malloc(size);
575*bbb1b6f9SApple OSS Distributions 
576*bbb1b6f9SApple OSS Distributions 	for (int i = 0; i < 64; i++) {
577*bbb1b6f9SApple OSS Distributions 		// Send a message.
578*bbb1b6f9SApple OSS Distributions 		ssize_t sent = write(socketA, random, size);
579*bbb1b6f9SApple OSS Distributions 		T_ASSERT_EQ_LONG(size, sent, "sent all bytes");
580*bbb1b6f9SApple OSS Distributions 
581*bbb1b6f9SApple OSS Distributions 		// Receive a message.
582*bbb1b6f9SApple OSS Distributions 		ssize_t read_bytes = read(socketB, buffer, size);
583*bbb1b6f9SApple OSS Distributions 		T_ASSERT_EQ_LONG(size, (unsigned long)read_bytes, "read all bytes");
584*bbb1b6f9SApple OSS Distributions 
585*bbb1b6f9SApple OSS Distributions 		// Sent and received same data.
586*bbb1b6f9SApple OSS Distributions 		T_ASSERT_EQ_INT(0, memcmp(random, buffer, size), "sent and received same data");
587*bbb1b6f9SApple OSS Distributions 	}
588*bbb1b6f9SApple OSS Distributions 
589*bbb1b6f9SApple OSS Distributions 	free(random);
590*bbb1b6f9SApple OSS Distributions 	vsock_close(socketA);
591*bbb1b6f9SApple OSS Distributions 	vsock_close(socketB);
592*bbb1b6f9SApple OSS Distributions }
593*bbb1b6f9SApple OSS Distributions 
594*bbb1b6f9SApple OSS Distributions /* Sysctl */
595*bbb1b6f9SApple OSS Distributions 
596*bbb1b6f9SApple OSS Distributions static const char* pcblist = "net.vsock.pcblist";
597*bbb1b6f9SApple OSS Distributions 
598*bbb1b6f9SApple OSS Distributions T_DECL(vsock_pcblist_simple, "vsock pcblist sysctl - simple")
599*bbb1b6f9SApple OSS Distributions {
600*bbb1b6f9SApple OSS Distributions 	// Create some socket to discover in the pcblist.
601*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
602*bbb1b6f9SApple OSS Distributions 	int socket;
603*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
604*bbb1b6f9SApple OSS Distributions 	int result = vsock_listen(VMADDR_CID_ANY, port, &addr, 10, &socket);
605*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock listen on a port");
606*bbb1b6f9SApple OSS Distributions 
607*bbb1b6f9SApple OSS Distributions 	// Get the buffer length for the pcblist.
608*bbb1b6f9SApple OSS Distributions 	size_t length = 0;
609*bbb1b6f9SApple OSS Distributions 	result = sysctlbyname(pcblist, 0, &length, 0, 0);
610*bbb1b6f9SApple OSS Distributions 	if (result == ENOENT) {
611*bbb1b6f9SApple OSS Distributions 		T_SKIP("%s missing", pcblist);
612*bbb1b6f9SApple OSS Distributions 	}
613*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock pcblist get buffer size (result %d)", result);
614*bbb1b6f9SApple OSS Distributions 
615*bbb1b6f9SApple OSS Distributions 	// Allocate the buffer.
616*bbb1b6f9SApple OSS Distributions 	struct xvsockpgen *buffer = malloc(length);
617*bbb1b6f9SApple OSS Distributions 	T_ASSERT_NOTNULL(buffer, "allocated buffer is not null");
618*bbb1b6f9SApple OSS Distributions 
619*bbb1b6f9SApple OSS Distributions 	// Populate the buffer with the pcblist.
620*bbb1b6f9SApple OSS Distributions 	result = sysctlbyname(pcblist, buffer, &length, 0, 0);
621*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock pcblist populate buffer");
622*bbb1b6f9SApple OSS Distributions 
623*bbb1b6f9SApple OSS Distributions 	// The socket should exist in the list.
624*bbb1b6f9SApple OSS Distributions 	bool exists = vsock_address_exists(buffer, addr);
625*bbb1b6f9SApple OSS Distributions 	T_ASSERT_TRUE(exists, "vsock pcblist contains the specified socket");
626*bbb1b6f9SApple OSS Distributions 
627*bbb1b6f9SApple OSS Distributions 	vsock_close(socket);
628*bbb1b6f9SApple OSS Distributions 	free(buffer);
629*bbb1b6f9SApple OSS Distributions }
630*bbb1b6f9SApple OSS Distributions 
631*bbb1b6f9SApple OSS Distributions T_DECL(vsock_pcblist_added, "vsock pcblist sysctl - socket added")
632*bbb1b6f9SApple OSS Distributions {
633*bbb1b6f9SApple OSS Distributions 	// Get the buffer length for the pcblist.
634*bbb1b6f9SApple OSS Distributions 	size_t length = 0;
635*bbb1b6f9SApple OSS Distributions 	int result = sysctlbyname(pcblist, 0, &length, 0, 0);
636*bbb1b6f9SApple OSS Distributions 	if (result == ENOENT) {
637*bbb1b6f9SApple OSS Distributions 		T_SKIP("%s missing", pcblist);
638*bbb1b6f9SApple OSS Distributions 	}
639*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock pcblist get buffer size (result %d)", result);
640*bbb1b6f9SApple OSS Distributions 
641*bbb1b6f9SApple OSS Distributions 	// Create some socket to discover in the pcblist after making the first sysctl.
642*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
643*bbb1b6f9SApple OSS Distributions 	int socket;
644*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
645*bbb1b6f9SApple OSS Distributions 	result = vsock_listen(VMADDR_CID_ANY, port, &addr, 10, &socket);
646*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock listen on a port");
647*bbb1b6f9SApple OSS Distributions 
648*bbb1b6f9SApple OSS Distributions 	// Allocate the buffer.
649*bbb1b6f9SApple OSS Distributions 	struct xvsockpgen *buffer = malloc(length);
650*bbb1b6f9SApple OSS Distributions 	T_ASSERT_NOTNULL(buffer, "allocated buffer is not null");
651*bbb1b6f9SApple OSS Distributions 
652*bbb1b6f9SApple OSS Distributions 	// Populate the buffer with the pcblist.
653*bbb1b6f9SApple OSS Distributions 	result = sysctlbyname(pcblist, buffer, &length, 0, 0);
654*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock pcblist populate buffer");
655*bbb1b6f9SApple OSS Distributions 
656*bbb1b6f9SApple OSS Distributions 	// The socket was created after the buffer and cannot fit.
657*bbb1b6f9SApple OSS Distributions 	bool exists = vsock_address_exists(buffer, addr);
658*bbb1b6f9SApple OSS Distributions 	T_ASSERT_FALSE(exists, "vsock pcblist should not contain the new socket");
659*bbb1b6f9SApple OSS Distributions 
660*bbb1b6f9SApple OSS Distributions 	vsock_close(socket);
661*bbb1b6f9SApple OSS Distributions 	free(buffer);
662*bbb1b6f9SApple OSS Distributions }
663*bbb1b6f9SApple OSS Distributions 
664*bbb1b6f9SApple OSS Distributions T_DECL(vsock_pcblist_removed, "vsock pcblist sysctl - socket removed")
665*bbb1b6f9SApple OSS Distributions {
666*bbb1b6f9SApple OSS Distributions 	// Create some socket to be removed after making the first sysctl.
667*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
668*bbb1b6f9SApple OSS Distributions 	int socket;
669*bbb1b6f9SApple OSS Distributions 	const uint32_t port = vsock_get_available_port();
670*bbb1b6f9SApple OSS Distributions 	int result = vsock_listen(VMADDR_CID_ANY, port, &addr, 10, &socket);
671*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock listen on a port");
672*bbb1b6f9SApple OSS Distributions 
673*bbb1b6f9SApple OSS Distributions 	// Get the buffer length for the pcblist.
674*bbb1b6f9SApple OSS Distributions 	size_t length = 0;
675*bbb1b6f9SApple OSS Distributions 	result = sysctlbyname(pcblist, 0, &length, 0, 0);
676*bbb1b6f9SApple OSS Distributions 	if (result == ENOENT) {
677*bbb1b6f9SApple OSS Distributions 		T_SKIP("%s missing", pcblist);
678*bbb1b6f9SApple OSS Distributions 	}
679*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock pcblist get buffer size (result %d)", result);
680*bbb1b6f9SApple OSS Distributions 
681*bbb1b6f9SApple OSS Distributions 	// Close the socket early.
682*bbb1b6f9SApple OSS Distributions 	vsock_close(socket);
683*bbb1b6f9SApple OSS Distributions 
684*bbb1b6f9SApple OSS Distributions 	// Allocate the buffer.
685*bbb1b6f9SApple OSS Distributions 	struct xvsockpgen *buffer = malloc(length);
686*bbb1b6f9SApple OSS Distributions 	T_ASSERT_NOTNULL(buffer, "allocated buffer is not null");
687*bbb1b6f9SApple OSS Distributions 
688*bbb1b6f9SApple OSS Distributions 	// Populate the buffer with the pcblist.
689*bbb1b6f9SApple OSS Distributions 	result = sysctlbyname(pcblist, buffer, &length, 0, 0);
690*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(result, "vsock pcblist populate buffer");
691*bbb1b6f9SApple OSS Distributions 
692*bbb1b6f9SApple OSS Distributions 	// The socket was destroyed before populating the list and should not exist.
693*bbb1b6f9SApple OSS Distributions 	bool exists = vsock_address_exists(buffer, addr);
694*bbb1b6f9SApple OSS Distributions 	T_ASSERT_FALSE(exists, "vsock pcblist should not contain the deleted socket");
695*bbb1b6f9SApple OSS Distributions 
696*bbb1b6f9SApple OSS Distributions 	free(buffer);
697*bbb1b6f9SApple OSS Distributions }
698*bbb1b6f9SApple OSS Distributions 
699*bbb1b6f9SApple OSS Distributions T_DECL(vsock_private_connect_without_entitlement, "vsock private connect should fail without entitlement")
700*bbb1b6f9SApple OSS Distributions {
701*bbb1b6f9SApple OSS Distributions 	int socket;
702*bbb1b6f9SApple OSS Distributions 	int result = vsock_private_connect(VMADDR_CID_HOST, 1234, &socket);
703*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EPERM, "vsock connect without entitlement");
704*bbb1b6f9SApple OSS Distributions }
705*bbb1b6f9SApple OSS Distributions 
706*bbb1b6f9SApple OSS Distributions T_DECL(vsock_private_bind_without_entitlement, "vsock private bind should fail without entitlement")
707*bbb1b6f9SApple OSS Distributions {
708*bbb1b6f9SApple OSS Distributions 	int socket;
709*bbb1b6f9SApple OSS Distributions 	struct sockaddr_vm addr;
710*bbb1b6f9SApple OSS Distributions 	int result = vsock_private_bind(VMADDR_CID_ANY, 1234, &addr, &socket);
711*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(result, EPERM, "vsock bind without entitlement");
712*bbb1b6f9SApple OSS Distributions }
713