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