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