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