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