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