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