xref: /xnu-10063.121.3/bsd/kern/vsock_domain.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions /*
2*2c2f96dcSApple OSS Distributions  * Copyright (c) 2020 Apple Inc. All rights reserved.
3*2c2f96dcSApple OSS Distributions  *
4*2c2f96dcSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*2c2f96dcSApple OSS Distributions  *
6*2c2f96dcSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*2c2f96dcSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*2c2f96dcSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*2c2f96dcSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*2c2f96dcSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*2c2f96dcSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*2c2f96dcSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*2c2f96dcSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*2c2f96dcSApple OSS Distributions  *
15*2c2f96dcSApple OSS Distributions  * Please obtain a copy of the License at
16*2c2f96dcSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*2c2f96dcSApple OSS Distributions  *
18*2c2f96dcSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*2c2f96dcSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*2c2f96dcSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*2c2f96dcSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*2c2f96dcSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*2c2f96dcSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*2c2f96dcSApple OSS Distributions  * limitations under the License.
25*2c2f96dcSApple OSS Distributions  *
26*2c2f96dcSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*2c2f96dcSApple OSS Distributions  */
28*2c2f96dcSApple OSS Distributions 
29*2c2f96dcSApple OSS Distributions #include <sys/domain.h>
30*2c2f96dcSApple OSS Distributions #include <sys/socket.h>
31*2c2f96dcSApple OSS Distributions #include <sys/protosw.h>
32*2c2f96dcSApple OSS Distributions #include <sys/mcache.h>
33*2c2f96dcSApple OSS Distributions #include <sys/systm.h>
34*2c2f96dcSApple OSS Distributions #include <sys/sysctl.h>
35*2c2f96dcSApple OSS Distributions #include <sys/random.h>
36*2c2f96dcSApple OSS Distributions #include <sys/mbuf.h>
37*2c2f96dcSApple OSS Distributions #include <sys/vsock_domain.h>
38*2c2f96dcSApple OSS Distributions #include <sys/vsock_transport.h>
39*2c2f96dcSApple OSS Distributions #include <kern/task.h>
40*2c2f96dcSApple OSS Distributions #include <kern/zalloc.h>
41*2c2f96dcSApple OSS Distributions #include <kern/locks.h>
42*2c2f96dcSApple OSS Distributions #include <machine/atomic.h>
43*2c2f96dcSApple OSS Distributions 
44*2c2f96dcSApple OSS Distributions #define sotovsockpcb(so) ((struct vsockpcb *)(so)->so_pcb)
45*2c2f96dcSApple OSS Distributions 
46*2c2f96dcSApple OSS Distributions #define VSOCK_PORT_RESERVED 1024
47*2c2f96dcSApple OSS Distributions 
48*2c2f96dcSApple OSS Distributions /* VSock Protocol Globals */
49*2c2f96dcSApple OSS Distributions 
50*2c2f96dcSApple OSS Distributions static struct vsock_transport * _Atomic the_vsock_transport = NULL;
51*2c2f96dcSApple OSS Distributions static ZONE_DEFINE(vsockpcb_zone, "vsockpcbzone",
52*2c2f96dcSApple OSS Distributions     sizeof(struct vsockpcb), ZC_NONE);
53*2c2f96dcSApple OSS Distributions static LCK_GRP_DECLARE(vsock_lock_grp, "vsock");
54*2c2f96dcSApple OSS Distributions static struct vsockpcbinfo vsockinfo;
55*2c2f96dcSApple OSS Distributions 
56*2c2f96dcSApple OSS Distributions static uint32_t vsock_sendspace = VSOCK_MAX_PACKET_SIZE * 8;
57*2c2f96dcSApple OSS Distributions static uint32_t vsock_recvspace = VSOCK_MAX_PACKET_SIZE * 8;
58*2c2f96dcSApple OSS Distributions 
59*2c2f96dcSApple OSS Distributions /* VSock PCB Helpers */
60*2c2f96dcSApple OSS Distributions 
61*2c2f96dcSApple OSS Distributions static uint32_t
vsock_get_peer_space(struct vsockpcb * pcb)62*2c2f96dcSApple OSS Distributions vsock_get_peer_space(struct vsockpcb *pcb)
63*2c2f96dcSApple OSS Distributions {
64*2c2f96dcSApple OSS Distributions 	return pcb->peer_buf_alloc - (pcb->tx_cnt - pcb->peer_fwd_cnt);
65*2c2f96dcSApple OSS Distributions }
66*2c2f96dcSApple OSS Distributions 
67*2c2f96dcSApple OSS Distributions static struct vsockpcb *
vsock_get_matching_pcb(struct vsock_address src,struct vsock_address dst)68*2c2f96dcSApple OSS Distributions vsock_get_matching_pcb(struct vsock_address src, struct vsock_address dst)
69*2c2f96dcSApple OSS Distributions {
70*2c2f96dcSApple OSS Distributions 	struct vsockpcb *preferred = NULL;
71*2c2f96dcSApple OSS Distributions 	struct vsockpcb *match = NULL;
72*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = NULL;
73*2c2f96dcSApple OSS Distributions 
74*2c2f96dcSApple OSS Distributions 	lck_rw_lock_shared(&vsockinfo.bound_lock);
75*2c2f96dcSApple OSS Distributions 	LIST_FOREACH(pcb, &vsockinfo.bound, bound) {
76*2c2f96dcSApple OSS Distributions 		// Source cid and port must match. Only destination port must match. (Allows for a changing CID during migration)
77*2c2f96dcSApple OSS Distributions 		socket_lock(pcb->so, 1);
78*2c2f96dcSApple OSS Distributions 		if ((pcb->so->so_state & SS_ISCONNECTED || pcb->so->so_state & SS_ISCONNECTING) &&
79*2c2f96dcSApple OSS Distributions 		    pcb->local_address.cid == src.cid && pcb->local_address.port == src.port &&
80*2c2f96dcSApple OSS Distributions 		    pcb->remote_address.port == dst.port) {
81*2c2f96dcSApple OSS Distributions 			preferred = pcb;
82*2c2f96dcSApple OSS Distributions 			break;
83*2c2f96dcSApple OSS Distributions 		} else if ((pcb->local_address.cid == src.cid || pcb->local_address.cid == VMADDR_CID_ANY) &&
84*2c2f96dcSApple OSS Distributions 		    pcb->local_address.port == src.port) {
85*2c2f96dcSApple OSS Distributions 			match = pcb;
86*2c2f96dcSApple OSS Distributions 		}
87*2c2f96dcSApple OSS Distributions 		socket_unlock(pcb->so, 1);
88*2c2f96dcSApple OSS Distributions 	}
89*2c2f96dcSApple OSS Distributions 	if (!preferred && match) {
90*2c2f96dcSApple OSS Distributions 		socket_lock(match->so, 1);
91*2c2f96dcSApple OSS Distributions 		preferred = match;
92*2c2f96dcSApple OSS Distributions 	}
93*2c2f96dcSApple OSS Distributions 	lck_rw_done(&vsockinfo.bound_lock);
94*2c2f96dcSApple OSS Distributions 
95*2c2f96dcSApple OSS Distributions 	return preferred;
96*2c2f96dcSApple OSS Distributions }
97*2c2f96dcSApple OSS Distributions 
98*2c2f96dcSApple OSS Distributions static errno_t
vsock_bind_address_if_free(struct vsockpcb * pcb,uint32_t local_cid,uint32_t local_port,uint32_t remote_cid,uint32_t remote_port)99*2c2f96dcSApple OSS Distributions vsock_bind_address_if_free(struct vsockpcb *pcb, uint32_t local_cid, uint32_t local_port, uint32_t remote_cid, uint32_t remote_port)
100*2c2f96dcSApple OSS Distributions {
101*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
102*2c2f96dcSApple OSS Distributions 
103*2c2f96dcSApple OSS Distributions 	// Privileged ports.
104*2c2f96dcSApple OSS Distributions 	if (local_port != VMADDR_PORT_ANY && local_port < VSOCK_PORT_RESERVED &&
105*2c2f96dcSApple OSS Distributions 	    current_task() != kernel_task && proc_suser(current_proc()) != 0) {
106*2c2f96dcSApple OSS Distributions 		return EACCES;
107*2c2f96dcSApple OSS Distributions 	}
108*2c2f96dcSApple OSS Distributions 
109*2c2f96dcSApple OSS Distributions 	bool taken = false;
110*2c2f96dcSApple OSS Distributions 	const bool check_remote = (remote_cid != VMADDR_CID_ANY && remote_port != VMADDR_PORT_ANY);
111*2c2f96dcSApple OSS Distributions 
112*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb_match = NULL;
113*2c2f96dcSApple OSS Distributions 
114*2c2f96dcSApple OSS Distributions 	socket_unlock(pcb->so, 0);
115*2c2f96dcSApple OSS Distributions 	lck_rw_lock_exclusive(&vsockinfo.bound_lock);
116*2c2f96dcSApple OSS Distributions 	LIST_FOREACH(pcb_match, &vsockinfo.bound, bound) {
117*2c2f96dcSApple OSS Distributions 		socket_lock(pcb_match->so, 1);
118*2c2f96dcSApple OSS Distributions 		if (pcb == pcb_match ||
119*2c2f96dcSApple OSS Distributions 		    (!check_remote && pcb_match->local_address.port == local_port) ||
120*2c2f96dcSApple OSS Distributions 		    (check_remote && pcb_match->local_address.port == local_port &&
121*2c2f96dcSApple OSS Distributions 		    pcb_match->remote_address.cid == remote_cid && pcb_match->remote_address.port == remote_port)) {
122*2c2f96dcSApple OSS Distributions 			socket_unlock(pcb_match->so, 1);
123*2c2f96dcSApple OSS Distributions 			taken = true;
124*2c2f96dcSApple OSS Distributions 			break;
125*2c2f96dcSApple OSS Distributions 		}
126*2c2f96dcSApple OSS Distributions 		socket_unlock(pcb_match->so, 1);
127*2c2f96dcSApple OSS Distributions 	}
128*2c2f96dcSApple OSS Distributions 	socket_lock(pcb->so, 0);
129*2c2f96dcSApple OSS Distributions 	if (!taken) {
130*2c2f96dcSApple OSS Distributions 		pcb->local_address = (struct vsock_address) { .cid = local_cid, .port = local_port };
131*2c2f96dcSApple OSS Distributions 		pcb->remote_address = (struct vsock_address) { .cid = remote_cid, .port = remote_port };
132*2c2f96dcSApple OSS Distributions 		LIST_INSERT_HEAD(&vsockinfo.bound, pcb, bound);
133*2c2f96dcSApple OSS Distributions 	}
134*2c2f96dcSApple OSS Distributions 	lck_rw_done(&vsockinfo.bound_lock);
135*2c2f96dcSApple OSS Distributions 
136*2c2f96dcSApple OSS Distributions 	return taken ? EADDRINUSE : 0;
137*2c2f96dcSApple OSS Distributions }
138*2c2f96dcSApple OSS Distributions 
139*2c2f96dcSApple OSS Distributions static errno_t
vsock_bind_address(struct vsockpcb * pcb,struct vsock_address laddr,struct vsock_address raddr)140*2c2f96dcSApple OSS Distributions vsock_bind_address(struct vsockpcb *pcb, struct vsock_address laddr, struct vsock_address raddr)
141*2c2f96dcSApple OSS Distributions {
142*2c2f96dcSApple OSS Distributions 	if (!pcb) {
143*2c2f96dcSApple OSS Distributions 		return EINVAL;
144*2c2f96dcSApple OSS Distributions 	}
145*2c2f96dcSApple OSS Distributions 
146*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
147*2c2f96dcSApple OSS Distributions 
148*2c2f96dcSApple OSS Distributions 	// Certain CIDs are reserved.
149*2c2f96dcSApple OSS Distributions 	if (laddr.cid == VMADDR_CID_HYPERVISOR || laddr.cid == VMADDR_CID_RESERVED || laddr.cid == VMADDR_CID_HOST) {
150*2c2f96dcSApple OSS Distributions 		return EADDRNOTAVAIL;
151*2c2f96dcSApple OSS Distributions 	}
152*2c2f96dcSApple OSS Distributions 
153*2c2f96dcSApple OSS Distributions 	// Remote address must be fully specified or not specified at all.
154*2c2f96dcSApple OSS Distributions 	if ((raddr.cid == VMADDR_CID_ANY) ^ (raddr.port == VMADDR_PORT_ANY)) {
155*2c2f96dcSApple OSS Distributions 		return EINVAL;
156*2c2f96dcSApple OSS Distributions 	}
157*2c2f96dcSApple OSS Distributions 
158*2c2f96dcSApple OSS Distributions 	// Cannot bind if already bound.
159*2c2f96dcSApple OSS Distributions 	if (pcb->local_address.port != VMADDR_PORT_ANY) {
160*2c2f96dcSApple OSS Distributions 		return EINVAL;
161*2c2f96dcSApple OSS Distributions 	}
162*2c2f96dcSApple OSS Distributions 
163*2c2f96dcSApple OSS Distributions 	uint32_t transport_cid;
164*2c2f96dcSApple OSS Distributions 	struct vsock_transport *transport = pcb->transport;
165*2c2f96dcSApple OSS Distributions 	errno_t error = transport->get_cid(transport->provider, &transport_cid);
166*2c2f96dcSApple OSS Distributions 	if (error) {
167*2c2f96dcSApple OSS Distributions 		return error;
168*2c2f96dcSApple OSS Distributions 	}
169*2c2f96dcSApple OSS Distributions 
170*2c2f96dcSApple OSS Distributions 	// Local CID must be this transport's CID or any.
171*2c2f96dcSApple OSS Distributions 	if (laddr.cid != transport_cid && laddr.cid != VMADDR_CID_ANY) {
172*2c2f96dcSApple OSS Distributions 		return EINVAL;
173*2c2f96dcSApple OSS Distributions 	}
174*2c2f96dcSApple OSS Distributions 
175*2c2f96dcSApple OSS Distributions 	if (laddr.port != VMADDR_PORT_ANY) {
176*2c2f96dcSApple OSS Distributions 		error = vsock_bind_address_if_free(pcb, laddr.cid, laddr.port, raddr.cid, raddr.port);
177*2c2f96dcSApple OSS Distributions 	} else {
178*2c2f96dcSApple OSS Distributions 		socket_unlock(pcb->so, 0);
179*2c2f96dcSApple OSS Distributions 		lck_mtx_lock(&vsockinfo.port_lock);
180*2c2f96dcSApple OSS Distributions 		socket_lock(pcb->so, 0);
181*2c2f96dcSApple OSS Distributions 
182*2c2f96dcSApple OSS Distributions 		const uint32_t first = VSOCK_PORT_RESERVED;
183*2c2f96dcSApple OSS Distributions 		const uint32_t last = VMADDR_PORT_ANY - 1;
184*2c2f96dcSApple OSS Distributions 		uint32_t count = last - first + 1;
185*2c2f96dcSApple OSS Distributions 		uint32_t *last_port = &vsockinfo.last_port;
186*2c2f96dcSApple OSS Distributions 
187*2c2f96dcSApple OSS Distributions 		if (pcb->so->so_flags & SOF_BINDRANDOMPORT) {
188*2c2f96dcSApple OSS Distributions 			uint32_t random = 0;
189*2c2f96dcSApple OSS Distributions 			read_frandom(&random, sizeof(random));
190*2c2f96dcSApple OSS Distributions 			*last_port = first + (random % count);
191*2c2f96dcSApple OSS Distributions 		}
192*2c2f96dcSApple OSS Distributions 
193*2c2f96dcSApple OSS Distributions 		do {
194*2c2f96dcSApple OSS Distributions 			if (count == 0) {
195*2c2f96dcSApple OSS Distributions 				lck_mtx_unlock(&vsockinfo.port_lock);
196*2c2f96dcSApple OSS Distributions 				return EADDRNOTAVAIL;
197*2c2f96dcSApple OSS Distributions 			}
198*2c2f96dcSApple OSS Distributions 			count--;
199*2c2f96dcSApple OSS Distributions 
200*2c2f96dcSApple OSS Distributions 			++*last_port;
201*2c2f96dcSApple OSS Distributions 			if (*last_port < first || *last_port > last) {
202*2c2f96dcSApple OSS Distributions 				*last_port = first;
203*2c2f96dcSApple OSS Distributions 			}
204*2c2f96dcSApple OSS Distributions 
205*2c2f96dcSApple OSS Distributions 			error = vsock_bind_address_if_free(pcb, laddr.cid, *last_port, raddr.cid, raddr.port);
206*2c2f96dcSApple OSS Distributions 		} while (error);
207*2c2f96dcSApple OSS Distributions 
208*2c2f96dcSApple OSS Distributions 		lck_mtx_unlock(&vsockinfo.port_lock);
209*2c2f96dcSApple OSS Distributions 	}
210*2c2f96dcSApple OSS Distributions 
211*2c2f96dcSApple OSS Distributions 	return error;
212*2c2f96dcSApple OSS Distributions }
213*2c2f96dcSApple OSS Distributions 
214*2c2f96dcSApple OSS Distributions static void
vsock_unbind_pcb_locked(struct vsockpcb * pcb,bool is_locked)215*2c2f96dcSApple OSS Distributions vsock_unbind_pcb_locked(struct vsockpcb *pcb, bool is_locked)
216*2c2f96dcSApple OSS Distributions {
217*2c2f96dcSApple OSS Distributions 	if (!pcb) {
218*2c2f96dcSApple OSS Distributions 		return;
219*2c2f96dcSApple OSS Distributions 	}
220*2c2f96dcSApple OSS Distributions 
221*2c2f96dcSApple OSS Distributions 	struct socket *so = pcb->so;
222*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(so);
223*2c2f96dcSApple OSS Distributions 
224*2c2f96dcSApple OSS Distributions 	// Bail if disconnect and already unbound.
225*2c2f96dcSApple OSS Distributions 	if (so->so_state & SS_ISDISCONNECTED) {
226*2c2f96dcSApple OSS Distributions 		assert(pcb->bound.le_next == NULL);
227*2c2f96dcSApple OSS Distributions 		assert(pcb->bound.le_prev == NULL);
228*2c2f96dcSApple OSS Distributions 		return;
229*2c2f96dcSApple OSS Distributions 	}
230*2c2f96dcSApple OSS Distributions 
231*2c2f96dcSApple OSS Distributions 	if (!is_locked) {
232*2c2f96dcSApple OSS Distributions 		socket_unlock(so, 0);
233*2c2f96dcSApple OSS Distributions 		lck_rw_lock_exclusive(&vsockinfo.bound_lock);
234*2c2f96dcSApple OSS Distributions 		socket_lock(so, 0);
235*2c2f96dcSApple OSS Distributions 
236*2c2f96dcSApple OSS Distributions 		// Case where some other thread also called unbind() on this socket while waiting to acquire its lock.
237*2c2f96dcSApple OSS Distributions 		if (!pcb->bound.le_prev) {
238*2c2f96dcSApple OSS Distributions 			soisdisconnected(so);
239*2c2f96dcSApple OSS Distributions 			lck_rw_done(&vsockinfo.bound_lock);
240*2c2f96dcSApple OSS Distributions 			return;
241*2c2f96dcSApple OSS Distributions 		}
242*2c2f96dcSApple OSS Distributions 	}
243*2c2f96dcSApple OSS Distributions 
244*2c2f96dcSApple OSS Distributions 	soisdisconnected(so);
245*2c2f96dcSApple OSS Distributions 
246*2c2f96dcSApple OSS Distributions 	LIST_REMOVE(pcb, bound);
247*2c2f96dcSApple OSS Distributions 	pcb->bound.le_next = NULL;
248*2c2f96dcSApple OSS Distributions 	pcb->bound.le_prev = NULL;
249*2c2f96dcSApple OSS Distributions 
250*2c2f96dcSApple OSS Distributions 	if (!is_locked) {
251*2c2f96dcSApple OSS Distributions 		lck_rw_done(&vsockinfo.bound_lock);
252*2c2f96dcSApple OSS Distributions 	}
253*2c2f96dcSApple OSS Distributions }
254*2c2f96dcSApple OSS Distributions 
255*2c2f96dcSApple OSS Distributions static void
vsock_unbind_pcb(struct vsockpcb * pcb)256*2c2f96dcSApple OSS Distributions vsock_unbind_pcb(struct vsockpcb *pcb)
257*2c2f96dcSApple OSS Distributions {
258*2c2f96dcSApple OSS Distributions 	vsock_unbind_pcb_locked(pcb, false);
259*2c2f96dcSApple OSS Distributions }
260*2c2f96dcSApple OSS Distributions 
261*2c2f96dcSApple OSS Distributions static struct sockaddr *
vsock_new_sockaddr(struct vsock_address * address)262*2c2f96dcSApple OSS Distributions vsock_new_sockaddr(struct vsock_address *address)
263*2c2f96dcSApple OSS Distributions {
264*2c2f96dcSApple OSS Distributions 	if (!address) {
265*2c2f96dcSApple OSS Distributions 		return NULL;
266*2c2f96dcSApple OSS Distributions 	}
267*2c2f96dcSApple OSS Distributions 
268*2c2f96dcSApple OSS Distributions 	struct sockaddr_vm *addr;
269*2c2f96dcSApple OSS Distributions 	addr = (struct sockaddr_vm *)alloc_sockaddr(sizeof(*addr),
270*2c2f96dcSApple OSS Distributions 	    Z_WAITOK | Z_NOFAIL);
271*2c2f96dcSApple OSS Distributions 
272*2c2f96dcSApple OSS Distributions 	addr->svm_family = AF_VSOCK;
273*2c2f96dcSApple OSS Distributions 	addr->svm_port = address->port;
274*2c2f96dcSApple OSS Distributions 	addr->svm_cid = address->cid;
275*2c2f96dcSApple OSS Distributions 
276*2c2f96dcSApple OSS Distributions 	return (struct sockaddr *)addr;
277*2c2f96dcSApple OSS Distributions }
278*2c2f96dcSApple OSS Distributions 
279*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_send_message(struct vsockpcb * pcb,enum vsock_operation operation,mbuf_t m)280*2c2f96dcSApple OSS Distributions vsock_pcb_send_message(struct vsockpcb *pcb, enum vsock_operation operation, mbuf_t m)
281*2c2f96dcSApple OSS Distributions {
282*2c2f96dcSApple OSS Distributions 	if (!pcb) {
283*2c2f96dcSApple OSS Distributions 		if (m != NULL) {
284*2c2f96dcSApple OSS Distributions 			mbuf_freem_list(m);
285*2c2f96dcSApple OSS Distributions 		}
286*2c2f96dcSApple OSS Distributions 		return EINVAL;
287*2c2f96dcSApple OSS Distributions 	}
288*2c2f96dcSApple OSS Distributions 
289*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
290*2c2f96dcSApple OSS Distributions 
291*2c2f96dcSApple OSS Distributions 	errno_t error;
292*2c2f96dcSApple OSS Distributions 
293*2c2f96dcSApple OSS Distributions 	struct vsock_address dst = pcb->remote_address;
294*2c2f96dcSApple OSS Distributions 	if (dst.cid == VMADDR_CID_ANY || dst.port == VMADDR_PORT_ANY) {
295*2c2f96dcSApple OSS Distributions 		if (m != NULL) {
296*2c2f96dcSApple OSS Distributions 			mbuf_freem_list(m);
297*2c2f96dcSApple OSS Distributions 		}
298*2c2f96dcSApple OSS Distributions 		return EINVAL;
299*2c2f96dcSApple OSS Distributions 	}
300*2c2f96dcSApple OSS Distributions 
301*2c2f96dcSApple OSS Distributions 	struct vsock_address src = pcb->local_address;
302*2c2f96dcSApple OSS Distributions 	if (src.cid == VMADDR_CID_ANY) {
303*2c2f96dcSApple OSS Distributions 		uint32_t transport_cid;
304*2c2f96dcSApple OSS Distributions 		struct vsock_transport *transport = pcb->transport;
305*2c2f96dcSApple OSS Distributions 		error = transport->get_cid(transport->provider, &transport_cid);
306*2c2f96dcSApple OSS Distributions 		if (error) {
307*2c2f96dcSApple OSS Distributions 			if (m != NULL) {
308*2c2f96dcSApple OSS Distributions 				mbuf_freem_list(m);
309*2c2f96dcSApple OSS Distributions 			}
310*2c2f96dcSApple OSS Distributions 			return error;
311*2c2f96dcSApple OSS Distributions 		}
312*2c2f96dcSApple OSS Distributions 		src.cid = transport_cid;
313*2c2f96dcSApple OSS Distributions 	}
314*2c2f96dcSApple OSS Distributions 
315*2c2f96dcSApple OSS Distributions 	uint32_t buf_alloc = pcb->so->so_rcv.sb_hiwat;
316*2c2f96dcSApple OSS Distributions 	uint32_t fwd_cnt = pcb->fwd_cnt;
317*2c2f96dcSApple OSS Distributions 
318*2c2f96dcSApple OSS Distributions 	if (src.cid == dst.cid) {
319*2c2f96dcSApple OSS Distributions 		pcb->last_buf_alloc = buf_alloc;
320*2c2f96dcSApple OSS Distributions 		pcb->last_fwd_cnt = fwd_cnt;
321*2c2f96dcSApple OSS Distributions 
322*2c2f96dcSApple OSS Distributions 		socket_unlock(pcb->so, 0);
323*2c2f96dcSApple OSS Distributions 		error = vsock_put_message(src, dst, operation, buf_alloc, fwd_cnt, m);
324*2c2f96dcSApple OSS Distributions 		socket_lock(pcb->so, 0);
325*2c2f96dcSApple OSS Distributions 	} else {
326*2c2f96dcSApple OSS Distributions 		struct vsock_transport *transport = pcb->transport;
327*2c2f96dcSApple OSS Distributions 		error = transport->put_message(transport->provider, src, dst, operation, buf_alloc, fwd_cnt, m);
328*2c2f96dcSApple OSS Distributions 
329*2c2f96dcSApple OSS Distributions 		if (!error) {
330*2c2f96dcSApple OSS Distributions 			pcb->last_buf_alloc = buf_alloc;
331*2c2f96dcSApple OSS Distributions 			pcb->last_fwd_cnt = fwd_cnt;
332*2c2f96dcSApple OSS Distributions 		}
333*2c2f96dcSApple OSS Distributions 	}
334*2c2f96dcSApple OSS Distributions 
335*2c2f96dcSApple OSS Distributions 	return error;
336*2c2f96dcSApple OSS Distributions }
337*2c2f96dcSApple OSS Distributions 
338*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_reset_address(struct vsock_address src,struct vsock_address dst)339*2c2f96dcSApple OSS Distributions vsock_pcb_reset_address(struct vsock_address src, struct vsock_address dst)
340*2c2f96dcSApple OSS Distributions {
341*2c2f96dcSApple OSS Distributions 	if (dst.cid == VMADDR_CID_ANY || dst.port == VMADDR_PORT_ANY) {
342*2c2f96dcSApple OSS Distributions 		return EINVAL;
343*2c2f96dcSApple OSS Distributions 	}
344*2c2f96dcSApple OSS Distributions 
345*2c2f96dcSApple OSS Distributions 	errno_t error = 0;
346*2c2f96dcSApple OSS Distributions 	struct vsock_transport *transport = NULL;
347*2c2f96dcSApple OSS Distributions 
348*2c2f96dcSApple OSS Distributions 	if (src.cid == VMADDR_CID_ANY) {
349*2c2f96dcSApple OSS Distributions 		transport = os_atomic_load(&the_vsock_transport, relaxed);
350*2c2f96dcSApple OSS Distributions 		if (transport == NULL) {
351*2c2f96dcSApple OSS Distributions 			return ENODEV;
352*2c2f96dcSApple OSS Distributions 		}
353*2c2f96dcSApple OSS Distributions 
354*2c2f96dcSApple OSS Distributions 		uint32_t transport_cid;
355*2c2f96dcSApple OSS Distributions 		error = transport->get_cid(transport->provider, &transport_cid);
356*2c2f96dcSApple OSS Distributions 		if (error) {
357*2c2f96dcSApple OSS Distributions 			return error;
358*2c2f96dcSApple OSS Distributions 		}
359*2c2f96dcSApple OSS Distributions 		src.cid = transport_cid;
360*2c2f96dcSApple OSS Distributions 	}
361*2c2f96dcSApple OSS Distributions 
362*2c2f96dcSApple OSS Distributions 	if (src.cid == dst.cid) {
363*2c2f96dcSApple OSS Distributions 		// Reset both sockets.
364*2c2f96dcSApple OSS Distributions 		struct vsockpcb *pcb = vsock_get_matching_pcb(src, dst);
365*2c2f96dcSApple OSS Distributions 		if (pcb) {
366*2c2f96dcSApple OSS Distributions 			socket_lock_assert_owned(pcb->so);
367*2c2f96dcSApple OSS Distributions 			vsock_unbind_pcb(pcb);
368*2c2f96dcSApple OSS Distributions 			socket_unlock(pcb->so, 1);
369*2c2f96dcSApple OSS Distributions 		}
370*2c2f96dcSApple OSS Distributions 	} else {
371*2c2f96dcSApple OSS Distributions 		if (!transport) {
372*2c2f96dcSApple OSS Distributions 			transport = os_atomic_load(&the_vsock_transport, relaxed);
373*2c2f96dcSApple OSS Distributions 			if (transport == NULL) {
374*2c2f96dcSApple OSS Distributions 				return ENODEV;
375*2c2f96dcSApple OSS Distributions 			}
376*2c2f96dcSApple OSS Distributions 		}
377*2c2f96dcSApple OSS Distributions 		error = transport->put_message(transport->provider, src, dst, VSOCK_RESET, 0, 0, NULL);
378*2c2f96dcSApple OSS Distributions 	}
379*2c2f96dcSApple OSS Distributions 
380*2c2f96dcSApple OSS Distributions 	return error;
381*2c2f96dcSApple OSS Distributions }
382*2c2f96dcSApple OSS Distributions 
383*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_safe_reset_address(struct vsockpcb * pcb,struct vsock_address src,struct vsock_address dst)384*2c2f96dcSApple OSS Distributions vsock_pcb_safe_reset_address(struct vsockpcb *pcb, struct vsock_address src, struct vsock_address dst)
385*2c2f96dcSApple OSS Distributions {
386*2c2f96dcSApple OSS Distributions 	if (pcb) {
387*2c2f96dcSApple OSS Distributions 		socket_lock_assert_owned(pcb->so);
388*2c2f96dcSApple OSS Distributions 		socket_unlock(pcb->so, 0);
389*2c2f96dcSApple OSS Distributions 	}
390*2c2f96dcSApple OSS Distributions 	errno_t error = vsock_pcb_reset_address(src, dst);
391*2c2f96dcSApple OSS Distributions 	if (pcb) {
392*2c2f96dcSApple OSS Distributions 		socket_lock(pcb->so, 0);
393*2c2f96dcSApple OSS Distributions 	}
394*2c2f96dcSApple OSS Distributions 	return error;
395*2c2f96dcSApple OSS Distributions }
396*2c2f96dcSApple OSS Distributions 
397*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_connect(struct vsockpcb * pcb)398*2c2f96dcSApple OSS Distributions vsock_pcb_connect(struct vsockpcb *pcb)
399*2c2f96dcSApple OSS Distributions {
400*2c2f96dcSApple OSS Distributions 	return vsock_pcb_send_message(pcb, VSOCK_REQUEST, NULL);
401*2c2f96dcSApple OSS Distributions }
402*2c2f96dcSApple OSS Distributions 
403*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_respond(struct vsockpcb * pcb)404*2c2f96dcSApple OSS Distributions vsock_pcb_respond(struct vsockpcb *pcb)
405*2c2f96dcSApple OSS Distributions {
406*2c2f96dcSApple OSS Distributions 	return vsock_pcb_send_message(pcb, VSOCK_RESPONSE, NULL);
407*2c2f96dcSApple OSS Distributions }
408*2c2f96dcSApple OSS Distributions 
409*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_send(struct vsockpcb * pcb,mbuf_t m)410*2c2f96dcSApple OSS Distributions vsock_pcb_send(struct vsockpcb *pcb, mbuf_t m)
411*2c2f96dcSApple OSS Distributions {
412*2c2f96dcSApple OSS Distributions 	return vsock_pcb_send_message(pcb, VSOCK_PAYLOAD, m);
413*2c2f96dcSApple OSS Distributions }
414*2c2f96dcSApple OSS Distributions 
415*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_shutdown_send(struct vsockpcb * pcb)416*2c2f96dcSApple OSS Distributions vsock_pcb_shutdown_send(struct vsockpcb *pcb)
417*2c2f96dcSApple OSS Distributions {
418*2c2f96dcSApple OSS Distributions 	return vsock_pcb_send_message(pcb, VSOCK_SHUTDOWN_SEND, NULL);
419*2c2f96dcSApple OSS Distributions }
420*2c2f96dcSApple OSS Distributions 
421*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_reset(struct vsockpcb * pcb)422*2c2f96dcSApple OSS Distributions vsock_pcb_reset(struct vsockpcb *pcb)
423*2c2f96dcSApple OSS Distributions {
424*2c2f96dcSApple OSS Distributions 	return vsock_pcb_send_message(pcb, VSOCK_RESET, NULL);
425*2c2f96dcSApple OSS Distributions }
426*2c2f96dcSApple OSS Distributions 
427*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_credit_update(struct vsockpcb * pcb)428*2c2f96dcSApple OSS Distributions vsock_pcb_credit_update(struct vsockpcb *pcb)
429*2c2f96dcSApple OSS Distributions {
430*2c2f96dcSApple OSS Distributions 	return vsock_pcb_send_message(pcb, VSOCK_CREDIT_UPDATE, NULL);
431*2c2f96dcSApple OSS Distributions }
432*2c2f96dcSApple OSS Distributions 
433*2c2f96dcSApple OSS Distributions static errno_t
vsock_pcb_credit_request(struct vsockpcb * pcb)434*2c2f96dcSApple OSS Distributions vsock_pcb_credit_request(struct vsockpcb *pcb)
435*2c2f96dcSApple OSS Distributions {
436*2c2f96dcSApple OSS Distributions 	return vsock_pcb_send_message(pcb, VSOCK_CREDIT_REQUEST, NULL);
437*2c2f96dcSApple OSS Distributions }
438*2c2f96dcSApple OSS Distributions 
439*2c2f96dcSApple OSS Distributions static errno_t
vsock_disconnect_pcb_common(struct vsockpcb * pcb,bool is_locked)440*2c2f96dcSApple OSS Distributions vsock_disconnect_pcb_common(struct vsockpcb *pcb, bool is_locked)
441*2c2f96dcSApple OSS Distributions {
442*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
443*2c2f96dcSApple OSS Distributions 	vsock_unbind_pcb_locked(pcb, is_locked);
444*2c2f96dcSApple OSS Distributions 	return vsock_pcb_reset(pcb);
445*2c2f96dcSApple OSS Distributions }
446*2c2f96dcSApple OSS Distributions 
447*2c2f96dcSApple OSS Distributions static errno_t
vsock_disconnect_pcb_locked(struct vsockpcb * pcb)448*2c2f96dcSApple OSS Distributions vsock_disconnect_pcb_locked(struct vsockpcb *pcb)
449*2c2f96dcSApple OSS Distributions {
450*2c2f96dcSApple OSS Distributions 	return vsock_disconnect_pcb_common(pcb, true);
451*2c2f96dcSApple OSS Distributions }
452*2c2f96dcSApple OSS Distributions 
453*2c2f96dcSApple OSS Distributions static errno_t
vsock_disconnect_pcb(struct vsockpcb * pcb)454*2c2f96dcSApple OSS Distributions vsock_disconnect_pcb(struct vsockpcb *pcb)
455*2c2f96dcSApple OSS Distributions {
456*2c2f96dcSApple OSS Distributions 	return vsock_disconnect_pcb_common(pcb, false);
457*2c2f96dcSApple OSS Distributions }
458*2c2f96dcSApple OSS Distributions 
459*2c2f96dcSApple OSS Distributions static errno_t
vsock_sockaddr_vm_validate(struct vsockpcb * pcb,struct sockaddr_vm * addr)460*2c2f96dcSApple OSS Distributions vsock_sockaddr_vm_validate(struct vsockpcb *pcb, struct sockaddr_vm *addr)
461*2c2f96dcSApple OSS Distributions {
462*2c2f96dcSApple OSS Distributions 	if (!pcb || !pcb->so || !addr) {
463*2c2f96dcSApple OSS Distributions 		return EINVAL;
464*2c2f96dcSApple OSS Distributions 	}
465*2c2f96dcSApple OSS Distributions 
466*2c2f96dcSApple OSS Distributions 	// Validate address length.
467*2c2f96dcSApple OSS Distributions 	if (addr->svm_len < sizeof(struct sockaddr_vm)) {
468*2c2f96dcSApple OSS Distributions 		return EINVAL;
469*2c2f96dcSApple OSS Distributions 	}
470*2c2f96dcSApple OSS Distributions 
471*2c2f96dcSApple OSS Distributions 	// Validate address family.
472*2c2f96dcSApple OSS Distributions 	if (addr->svm_family != AF_UNSPEC && addr->svm_family != AF_VSOCK) {
473*2c2f96dcSApple OSS Distributions 		return EAFNOSUPPORT;
474*2c2f96dcSApple OSS Distributions 	}
475*2c2f96dcSApple OSS Distributions 
476*2c2f96dcSApple OSS Distributions 	// Only stream is supported currently.
477*2c2f96dcSApple OSS Distributions 	if (pcb->so->so_type != SOCK_STREAM) {
478*2c2f96dcSApple OSS Distributions 		return EAFNOSUPPORT;
479*2c2f96dcSApple OSS Distributions 	}
480*2c2f96dcSApple OSS Distributions 
481*2c2f96dcSApple OSS Distributions 	return 0;
482*2c2f96dcSApple OSS Distributions }
483*2c2f96dcSApple OSS Distributions 
484*2c2f96dcSApple OSS Distributions /* VSock Receive Handlers */
485*2c2f96dcSApple OSS Distributions 
486*2c2f96dcSApple OSS Distributions static errno_t
vsock_put_message_connected(struct vsockpcb * pcb,enum vsock_operation op,mbuf_t m)487*2c2f96dcSApple OSS Distributions vsock_put_message_connected(struct vsockpcb *pcb, enum vsock_operation op, mbuf_t m)
488*2c2f96dcSApple OSS Distributions {
489*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
490*2c2f96dcSApple OSS Distributions 
491*2c2f96dcSApple OSS Distributions 	errno_t error = 0;
492*2c2f96dcSApple OSS Distributions 
493*2c2f96dcSApple OSS Distributions 	switch (op) {
494*2c2f96dcSApple OSS Distributions 	case VSOCK_SHUTDOWN:
495*2c2f96dcSApple OSS Distributions 		socantsendmore(pcb->so);
496*2c2f96dcSApple OSS Distributions 		socantrcvmore(pcb->so);
497*2c2f96dcSApple OSS Distributions 		break;
498*2c2f96dcSApple OSS Distributions 	case VSOCK_SHUTDOWN_RECEIVE:
499*2c2f96dcSApple OSS Distributions 		socantsendmore(pcb->so);
500*2c2f96dcSApple OSS Distributions 		break;
501*2c2f96dcSApple OSS Distributions 	case VSOCK_SHUTDOWN_SEND:
502*2c2f96dcSApple OSS Distributions 		socantrcvmore(pcb->so);
503*2c2f96dcSApple OSS Distributions 		break;
504*2c2f96dcSApple OSS Distributions 	case VSOCK_PAYLOAD:
505*2c2f96dcSApple OSS Distributions 		// Add data to the receive queue then wakeup any reading threads.
506*2c2f96dcSApple OSS Distributions 		error = !sbappendstream(&pcb->so->so_rcv, m);
507*2c2f96dcSApple OSS Distributions 		if (!error) {
508*2c2f96dcSApple OSS Distributions 			sorwakeup(pcb->so);
509*2c2f96dcSApple OSS Distributions 		}
510*2c2f96dcSApple OSS Distributions 		break;
511*2c2f96dcSApple OSS Distributions 	case VSOCK_RESET:
512*2c2f96dcSApple OSS Distributions 		vsock_unbind_pcb(pcb);
513*2c2f96dcSApple OSS Distributions 		break;
514*2c2f96dcSApple OSS Distributions 	default:
515*2c2f96dcSApple OSS Distributions 		error = ENOTSUP;
516*2c2f96dcSApple OSS Distributions 		break;
517*2c2f96dcSApple OSS Distributions 	}
518*2c2f96dcSApple OSS Distributions 
519*2c2f96dcSApple OSS Distributions 	return error;
520*2c2f96dcSApple OSS Distributions }
521*2c2f96dcSApple OSS Distributions 
522*2c2f96dcSApple OSS Distributions static errno_t
vsock_put_message_connecting(struct vsockpcb * pcb,enum vsock_operation op)523*2c2f96dcSApple OSS Distributions vsock_put_message_connecting(struct vsockpcb *pcb, enum vsock_operation op)
524*2c2f96dcSApple OSS Distributions {
525*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
526*2c2f96dcSApple OSS Distributions 
527*2c2f96dcSApple OSS Distributions 	errno_t error = 0;
528*2c2f96dcSApple OSS Distributions 
529*2c2f96dcSApple OSS Distributions 	switch (op) {
530*2c2f96dcSApple OSS Distributions 	case VSOCK_RESPONSE:
531*2c2f96dcSApple OSS Distributions 		soisconnected(pcb->so);
532*2c2f96dcSApple OSS Distributions 		break;
533*2c2f96dcSApple OSS Distributions 	case VSOCK_RESET:
534*2c2f96dcSApple OSS Distributions 		pcb->so->so_error = EAGAIN;
535*2c2f96dcSApple OSS Distributions 		error = vsock_disconnect_pcb(pcb);
536*2c2f96dcSApple OSS Distributions 		break;
537*2c2f96dcSApple OSS Distributions 	default:
538*2c2f96dcSApple OSS Distributions 		vsock_disconnect_pcb(pcb);
539*2c2f96dcSApple OSS Distributions 		error = ENOTSUP;
540*2c2f96dcSApple OSS Distributions 		break;
541*2c2f96dcSApple OSS Distributions 	}
542*2c2f96dcSApple OSS Distributions 
543*2c2f96dcSApple OSS Distributions 	return error;
544*2c2f96dcSApple OSS Distributions }
545*2c2f96dcSApple OSS Distributions 
546*2c2f96dcSApple OSS Distributions static errno_t
vsock_put_message_listening(struct vsockpcb * pcb,enum vsock_operation op,struct vsock_address src,struct vsock_address dst)547*2c2f96dcSApple OSS Distributions vsock_put_message_listening(struct vsockpcb *pcb, enum vsock_operation op, struct vsock_address src, struct vsock_address dst)
548*2c2f96dcSApple OSS Distributions {
549*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
550*2c2f96dcSApple OSS Distributions 
551*2c2f96dcSApple OSS Distributions 	struct sockaddr_vm addr;
552*2c2f96dcSApple OSS Distributions 	struct socket *so2 = NULL;
553*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb2 = NULL;
554*2c2f96dcSApple OSS Distributions 
555*2c2f96dcSApple OSS Distributions 	errno_t error = 0;
556*2c2f96dcSApple OSS Distributions 
557*2c2f96dcSApple OSS Distributions 	switch (op) {
558*2c2f96dcSApple OSS Distributions 	case VSOCK_REQUEST:
559*2c2f96dcSApple OSS Distributions 		addr = (struct sockaddr_vm) {
560*2c2f96dcSApple OSS Distributions 			.svm_len = sizeof(addr),
561*2c2f96dcSApple OSS Distributions 			.svm_family = AF_VSOCK,
562*2c2f96dcSApple OSS Distributions 			.svm_reserved1 = 0,
563*2c2f96dcSApple OSS Distributions 			.svm_port = pcb->local_address.port,
564*2c2f96dcSApple OSS Distributions 			.svm_cid = pcb->local_address.cid
565*2c2f96dcSApple OSS Distributions 		};
566*2c2f96dcSApple OSS Distributions 		so2 = sonewconn(pcb->so, 0, (struct sockaddr *)&addr);
567*2c2f96dcSApple OSS Distributions 		if (!so2) {
568*2c2f96dcSApple OSS Distributions 			// It is likely that the backlog is full. Deny this request.
569*2c2f96dcSApple OSS Distributions 			vsock_pcb_safe_reset_address(pcb, dst, src);
570*2c2f96dcSApple OSS Distributions 			error = ECONNREFUSED;
571*2c2f96dcSApple OSS Distributions 			break;
572*2c2f96dcSApple OSS Distributions 		}
573*2c2f96dcSApple OSS Distributions 
574*2c2f96dcSApple OSS Distributions 		pcb2 = sotovsockpcb(so2);
575*2c2f96dcSApple OSS Distributions 		if (!pcb2) {
576*2c2f96dcSApple OSS Distributions 			error = EINVAL;
577*2c2f96dcSApple OSS Distributions 			goto done;
578*2c2f96dcSApple OSS Distributions 		}
579*2c2f96dcSApple OSS Distributions 
580*2c2f96dcSApple OSS Distributions 		error = vsock_bind_address(pcb2, dst, src);
581*2c2f96dcSApple OSS Distributions 		if (error) {
582*2c2f96dcSApple OSS Distributions 			goto done;
583*2c2f96dcSApple OSS Distributions 		}
584*2c2f96dcSApple OSS Distributions 
585*2c2f96dcSApple OSS Distributions 		error = vsock_pcb_respond(pcb2);
586*2c2f96dcSApple OSS Distributions 		if (error) {
587*2c2f96dcSApple OSS Distributions 			goto done;
588*2c2f96dcSApple OSS Distributions 		}
589*2c2f96dcSApple OSS Distributions 
590*2c2f96dcSApple OSS Distributions 		soisconnected(so2);
591*2c2f96dcSApple OSS Distributions 
592*2c2f96dcSApple OSS Distributions done:
593*2c2f96dcSApple OSS Distributions 		if (error) {
594*2c2f96dcSApple OSS Distributions 			if (pcb2) {
595*2c2f96dcSApple OSS Distributions 				vsock_unbind_pcb(pcb2);
596*2c2f96dcSApple OSS Distributions 			} else {
597*2c2f96dcSApple OSS Distributions 				soisdisconnected(so2);
598*2c2f96dcSApple OSS Distributions 			}
599*2c2f96dcSApple OSS Distributions 			socket_unlock(so2, 1);
600*2c2f96dcSApple OSS Distributions 			vsock_pcb_reset_address(dst, src);
601*2c2f96dcSApple OSS Distributions 		} else {
602*2c2f96dcSApple OSS Distributions 			socket_unlock(so2, 0);
603*2c2f96dcSApple OSS Distributions 		}
604*2c2f96dcSApple OSS Distributions 		socket_lock(pcb->so, 0);
605*2c2f96dcSApple OSS Distributions 
606*2c2f96dcSApple OSS Distributions 		break;
607*2c2f96dcSApple OSS Distributions 	case VSOCK_RESET:
608*2c2f96dcSApple OSS Distributions 		error = vsock_pcb_safe_reset_address(pcb, dst, src);
609*2c2f96dcSApple OSS Distributions 		break;
610*2c2f96dcSApple OSS Distributions 	default:
611*2c2f96dcSApple OSS Distributions 		vsock_pcb_safe_reset_address(pcb, dst, src);
612*2c2f96dcSApple OSS Distributions 		error = ENOTSUP;
613*2c2f96dcSApple OSS Distributions 		break;
614*2c2f96dcSApple OSS Distributions 	}
615*2c2f96dcSApple OSS Distributions 
616*2c2f96dcSApple OSS Distributions 	return error;
617*2c2f96dcSApple OSS Distributions }
618*2c2f96dcSApple OSS Distributions 
619*2c2f96dcSApple OSS Distributions /* VSock Transport */
620*2c2f96dcSApple OSS Distributions 
621*2c2f96dcSApple OSS Distributions errno_t
vsock_add_transport(struct vsock_transport * transport)622*2c2f96dcSApple OSS Distributions vsock_add_transport(struct vsock_transport *transport)
623*2c2f96dcSApple OSS Distributions {
624*2c2f96dcSApple OSS Distributions 	if (transport == NULL || transport->provider == NULL) {
625*2c2f96dcSApple OSS Distributions 		return EINVAL;
626*2c2f96dcSApple OSS Distributions 	}
627*2c2f96dcSApple OSS Distributions 	if (!os_atomic_cmpxchg((void * volatile *)&the_vsock_transport, NULL, transport, acq_rel)) {
628*2c2f96dcSApple OSS Distributions 		return EEXIST;
629*2c2f96dcSApple OSS Distributions 	}
630*2c2f96dcSApple OSS Distributions 	return 0;
631*2c2f96dcSApple OSS Distributions }
632*2c2f96dcSApple OSS Distributions 
633*2c2f96dcSApple OSS Distributions errno_t
vsock_remove_transport(struct vsock_transport * transport)634*2c2f96dcSApple OSS Distributions vsock_remove_transport(struct vsock_transport *transport)
635*2c2f96dcSApple OSS Distributions {
636*2c2f96dcSApple OSS Distributions 	if (!os_atomic_cmpxchg((void * volatile *)&the_vsock_transport, transport, NULL, acq_rel)) {
637*2c2f96dcSApple OSS Distributions 		return ENODEV;
638*2c2f96dcSApple OSS Distributions 	}
639*2c2f96dcSApple OSS Distributions 	return 0;
640*2c2f96dcSApple OSS Distributions }
641*2c2f96dcSApple OSS Distributions 
642*2c2f96dcSApple OSS Distributions errno_t
vsock_reset_transport(struct vsock_transport * transport)643*2c2f96dcSApple OSS Distributions vsock_reset_transport(struct vsock_transport *transport)
644*2c2f96dcSApple OSS Distributions {
645*2c2f96dcSApple OSS Distributions 	if (transport == NULL) {
646*2c2f96dcSApple OSS Distributions 		return EINVAL;
647*2c2f96dcSApple OSS Distributions 	}
648*2c2f96dcSApple OSS Distributions 
649*2c2f96dcSApple OSS Distributions 	errno_t error = 0;
650*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = NULL;
651*2c2f96dcSApple OSS Distributions 	struct vsockpcb *tmp_pcb = NULL;
652*2c2f96dcSApple OSS Distributions 
653*2c2f96dcSApple OSS Distributions 	lck_rw_lock_exclusive(&vsockinfo.bound_lock);
654*2c2f96dcSApple OSS Distributions 	LIST_FOREACH_SAFE(pcb, &vsockinfo.bound, bound, tmp_pcb) {
655*2c2f96dcSApple OSS Distributions 		// Disconnect this transport's sockets. Listen and bind sockets must stay alive.
656*2c2f96dcSApple OSS Distributions 		socket_lock(pcb->so, 1);
657*2c2f96dcSApple OSS Distributions 		if (pcb->transport == transport && pcb->so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) {
658*2c2f96dcSApple OSS Distributions 			errno_t dc_error = vsock_disconnect_pcb_locked(pcb);
659*2c2f96dcSApple OSS Distributions 			if (dc_error && !error) {
660*2c2f96dcSApple OSS Distributions 				error = dc_error;
661*2c2f96dcSApple OSS Distributions 			}
662*2c2f96dcSApple OSS Distributions 		}
663*2c2f96dcSApple OSS Distributions 		socket_unlock(pcb->so, 1);
664*2c2f96dcSApple OSS Distributions 	}
665*2c2f96dcSApple OSS Distributions 	lck_rw_done(&vsockinfo.bound_lock);
666*2c2f96dcSApple OSS Distributions 
667*2c2f96dcSApple OSS Distributions 	return error;
668*2c2f96dcSApple OSS Distributions }
669*2c2f96dcSApple OSS Distributions 
670*2c2f96dcSApple OSS Distributions errno_t
vsock_put_message(struct vsock_address src,struct vsock_address dst,enum vsock_operation op,uint32_t buf_alloc,uint32_t fwd_cnt,mbuf_t m)671*2c2f96dcSApple OSS Distributions vsock_put_message(struct vsock_address src, struct vsock_address dst, enum vsock_operation op, uint32_t buf_alloc, uint32_t fwd_cnt, mbuf_t m)
672*2c2f96dcSApple OSS Distributions {
673*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = vsock_get_matching_pcb(dst, src);
674*2c2f96dcSApple OSS Distributions 	if (!pcb) {
675*2c2f96dcSApple OSS Distributions 		if (op != VSOCK_RESET) {
676*2c2f96dcSApple OSS Distributions 			vsock_pcb_reset_address(dst, src);
677*2c2f96dcSApple OSS Distributions 		}
678*2c2f96dcSApple OSS Distributions 		if (m != NULL) {
679*2c2f96dcSApple OSS Distributions 			mbuf_freem_list(m);
680*2c2f96dcSApple OSS Distributions 		}
681*2c2f96dcSApple OSS Distributions 		return EINVAL;
682*2c2f96dcSApple OSS Distributions 	}
683*2c2f96dcSApple OSS Distributions 
684*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(pcb->so);
685*2c2f96dcSApple OSS Distributions 
686*2c2f96dcSApple OSS Distributions 	struct socket *so = pcb->so;
687*2c2f96dcSApple OSS Distributions 	errno_t error = 0;
688*2c2f96dcSApple OSS Distributions 
689*2c2f96dcSApple OSS Distributions 	// Check if the peer's buffer has changed. Update our view of the peer's forwarded bytes.
690*2c2f96dcSApple OSS Distributions 	int buffers_changed = (pcb->peer_buf_alloc != buf_alloc) || (pcb->peer_fwd_cnt) != fwd_cnt;
691*2c2f96dcSApple OSS Distributions 	pcb->peer_buf_alloc = buf_alloc;
692*2c2f96dcSApple OSS Distributions 	pcb->peer_fwd_cnt = fwd_cnt;
693*2c2f96dcSApple OSS Distributions 
694*2c2f96dcSApple OSS Distributions 	// Peer's buffer has enough space for the next packet. Notify any threads waiting for space.
695*2c2f96dcSApple OSS Distributions 	if (buffers_changed && vsock_get_peer_space(pcb) >= pcb->waiting_send_size) {
696*2c2f96dcSApple OSS Distributions 		sowwakeup(so);
697*2c2f96dcSApple OSS Distributions 	}
698*2c2f96dcSApple OSS Distributions 
699*2c2f96dcSApple OSS Distributions 	switch (op) {
700*2c2f96dcSApple OSS Distributions 	case VSOCK_CREDIT_REQUEST:
701*2c2f96dcSApple OSS Distributions 		error = vsock_pcb_credit_update(pcb);
702*2c2f96dcSApple OSS Distributions 		break;
703*2c2f96dcSApple OSS Distributions 	case VSOCK_CREDIT_UPDATE:
704*2c2f96dcSApple OSS Distributions 		break;
705*2c2f96dcSApple OSS Distributions 	default:
706*2c2f96dcSApple OSS Distributions 		if (so->so_state & SS_ISCONNECTED) {
707*2c2f96dcSApple OSS Distributions 			error = vsock_put_message_connected(pcb, op, m);
708*2c2f96dcSApple OSS Distributions 			m = NULL;
709*2c2f96dcSApple OSS Distributions 		} else if (so->so_state & SS_ISCONNECTING) {
710*2c2f96dcSApple OSS Distributions 			error = vsock_put_message_connecting(pcb, op);
711*2c2f96dcSApple OSS Distributions 		} else if (so->so_options & SO_ACCEPTCONN) {
712*2c2f96dcSApple OSS Distributions 			error = vsock_put_message_listening(pcb, op, src, dst);
713*2c2f96dcSApple OSS Distributions 		} else {
714*2c2f96dcSApple OSS Distributions 			// Reset the connection for other states such as 'disconnecting'.
715*2c2f96dcSApple OSS Distributions 			error = vsock_disconnect_pcb(pcb);
716*2c2f96dcSApple OSS Distributions 			if (!error) {
717*2c2f96dcSApple OSS Distributions 				error = ENODEV;
718*2c2f96dcSApple OSS Distributions 			}
719*2c2f96dcSApple OSS Distributions 		}
720*2c2f96dcSApple OSS Distributions 		break;
721*2c2f96dcSApple OSS Distributions 	}
722*2c2f96dcSApple OSS Distributions 	socket_unlock(so, 1);
723*2c2f96dcSApple OSS Distributions 
724*2c2f96dcSApple OSS Distributions 	if (m != NULL) {
725*2c2f96dcSApple OSS Distributions 		mbuf_freem_list(m);
726*2c2f96dcSApple OSS Distributions 	}
727*2c2f96dcSApple OSS Distributions 
728*2c2f96dcSApple OSS Distributions 	return error;
729*2c2f96dcSApple OSS Distributions }
730*2c2f96dcSApple OSS Distributions 
731*2c2f96dcSApple OSS Distributions /* VSock Sysctl */
732*2c2f96dcSApple OSS Distributions 
733*2c2f96dcSApple OSS Distributions static int
734*2c2f96dcSApple OSS Distributions vsock_pcblist SYSCTL_HANDLER_ARGS
735*2c2f96dcSApple OSS Distributions {
736*2c2f96dcSApple OSS Distributions #pragma unused(oidp,arg2)
737*2c2f96dcSApple OSS Distributions 
738*2c2f96dcSApple OSS Distributions 	int error;
739*2c2f96dcSApple OSS Distributions 
740*2c2f96dcSApple OSS Distributions 	// Only stream is supported.
741*2c2f96dcSApple OSS Distributions 	if ((intptr_t)arg1 != SOCK_STREAM) {
742*2c2f96dcSApple OSS Distributions 		return EINVAL;
743*2c2f96dcSApple OSS Distributions 	}
744*2c2f96dcSApple OSS Distributions 
745*2c2f96dcSApple OSS Distributions 	// Get the generation count and the count of all vsock sockets.
746*2c2f96dcSApple OSS Distributions 	lck_rw_lock_shared(&vsockinfo.all_lock);
747*2c2f96dcSApple OSS Distributions 	uint64_t n = vsockinfo.all_pcb_count;
748*2c2f96dcSApple OSS Distributions 	vsock_gen_t gen_count = vsockinfo.vsock_gencnt;
749*2c2f96dcSApple OSS Distributions 	lck_rw_done(&vsockinfo.all_lock);
750*2c2f96dcSApple OSS Distributions 
751*2c2f96dcSApple OSS Distributions 	const size_t xpcb_len = sizeof(struct xvsockpcb);
752*2c2f96dcSApple OSS Distributions 	struct xvsockpgen xvg;
753*2c2f96dcSApple OSS Distributions 
754*2c2f96dcSApple OSS Distributions 	/*
755*2c2f96dcSApple OSS Distributions 	 * The process of preparing the PCB list is too time-consuming and
756*2c2f96dcSApple OSS Distributions 	 * resource-intensive to repeat twice on every request.
757*2c2f96dcSApple OSS Distributions 	 */
758*2c2f96dcSApple OSS Distributions 	if (req->oldptr == USER_ADDR_NULL) {
759*2c2f96dcSApple OSS Distributions 		req->oldidx = (size_t)(2 * sizeof(xvg) + (n + n / 8) * xpcb_len);
760*2c2f96dcSApple OSS Distributions 		return 0;
761*2c2f96dcSApple OSS Distributions 	}
762*2c2f96dcSApple OSS Distributions 
763*2c2f96dcSApple OSS Distributions 	if (req->newptr != USER_ADDR_NULL) {
764*2c2f96dcSApple OSS Distributions 		return EPERM;
765*2c2f96dcSApple OSS Distributions 	}
766*2c2f96dcSApple OSS Distributions 
767*2c2f96dcSApple OSS Distributions 	bzero(&xvg, sizeof(xvg));
768*2c2f96dcSApple OSS Distributions 	xvg.xvg_len = sizeof(xvg);
769*2c2f96dcSApple OSS Distributions 	xvg.xvg_count = n;
770*2c2f96dcSApple OSS Distributions 	xvg.xvg_gen = gen_count;
771*2c2f96dcSApple OSS Distributions 	xvg.xvg_sogen = so_gencnt;
772*2c2f96dcSApple OSS Distributions 	error = SYSCTL_OUT(req, &xvg, sizeof(xvg));
773*2c2f96dcSApple OSS Distributions 	if (error) {
774*2c2f96dcSApple OSS Distributions 		return error;
775*2c2f96dcSApple OSS Distributions 	}
776*2c2f96dcSApple OSS Distributions 
777*2c2f96dcSApple OSS Distributions 	// Return if no sockets exist.
778*2c2f96dcSApple OSS Distributions 	if (n == 0) {
779*2c2f96dcSApple OSS Distributions 		return 0;
780*2c2f96dcSApple OSS Distributions 	}
781*2c2f96dcSApple OSS Distributions 
782*2c2f96dcSApple OSS Distributions 	lck_rw_lock_shared(&vsockinfo.all_lock);
783*2c2f96dcSApple OSS Distributions 
784*2c2f96dcSApple OSS Distributions 	n = 0;
785*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = NULL;
786*2c2f96dcSApple OSS Distributions 	TAILQ_FOREACH(pcb, &vsockinfo.all, all) {
787*2c2f96dcSApple OSS Distributions 		// Bail if there is not enough user buffer for this next socket.
788*2c2f96dcSApple OSS Distributions 		if (req->oldlen - req->oldidx - sizeof(xvg) < xpcb_len) {
789*2c2f96dcSApple OSS Distributions 			break;
790*2c2f96dcSApple OSS Distributions 		}
791*2c2f96dcSApple OSS Distributions 
792*2c2f96dcSApple OSS Distributions 		// Populate the socket structure.
793*2c2f96dcSApple OSS Distributions 		socket_lock(pcb->so, 1);
794*2c2f96dcSApple OSS Distributions 		if (pcb->vsock_gencnt <= gen_count) {
795*2c2f96dcSApple OSS Distributions 			struct xvsockpcb xpcb;
796*2c2f96dcSApple OSS Distributions 			bzero(&xpcb, xpcb_len);
797*2c2f96dcSApple OSS Distributions 			xpcb.xv_len = xpcb_len;
798*2c2f96dcSApple OSS Distributions 			xpcb.xv_vsockpp = (uint64_t)VM_KERNEL_ADDRHASH(pcb);
799*2c2f96dcSApple OSS Distributions 			xpcb.xvp_local_cid = pcb->local_address.cid;
800*2c2f96dcSApple OSS Distributions 			xpcb.xvp_local_port = pcb->local_address.port;
801*2c2f96dcSApple OSS Distributions 			xpcb.xvp_remote_cid = pcb->remote_address.cid;
802*2c2f96dcSApple OSS Distributions 			xpcb.xvp_remote_port = pcb->remote_address.port;
803*2c2f96dcSApple OSS Distributions 			xpcb.xvp_rxcnt = pcb->fwd_cnt;
804*2c2f96dcSApple OSS Distributions 			xpcb.xvp_txcnt = pcb->tx_cnt;
805*2c2f96dcSApple OSS Distributions 			xpcb.xvp_peer_rxhiwat = pcb->peer_buf_alloc;
806*2c2f96dcSApple OSS Distributions 			xpcb.xvp_peer_rxcnt = pcb->peer_fwd_cnt;
807*2c2f96dcSApple OSS Distributions 			xpcb.xvp_last_pid = pcb->so->last_pid;
808*2c2f96dcSApple OSS Distributions 			xpcb.xvp_gencnt = pcb->vsock_gencnt;
809*2c2f96dcSApple OSS Distributions 			if (pcb->so) {
810*2c2f96dcSApple OSS Distributions 				sotoxsocket(pcb->so, &xpcb.xv_socket);
811*2c2f96dcSApple OSS Distributions 			}
812*2c2f96dcSApple OSS Distributions 			socket_unlock(pcb->so, 1);
813*2c2f96dcSApple OSS Distributions 
814*2c2f96dcSApple OSS Distributions 			error = SYSCTL_OUT(req, &xpcb, xpcb_len);
815*2c2f96dcSApple OSS Distributions 			if (error != 0) {
816*2c2f96dcSApple OSS Distributions 				break;
817*2c2f96dcSApple OSS Distributions 			}
818*2c2f96dcSApple OSS Distributions 			n++;
819*2c2f96dcSApple OSS Distributions 		} else {
820*2c2f96dcSApple OSS Distributions 			socket_unlock(pcb->so, 1);
821*2c2f96dcSApple OSS Distributions 		}
822*2c2f96dcSApple OSS Distributions 	}
823*2c2f96dcSApple OSS Distributions 
824*2c2f96dcSApple OSS Distributions 	// Update the generation count to match the sockets being returned.
825*2c2f96dcSApple OSS Distributions 	gen_count = vsockinfo.vsock_gencnt;
826*2c2f96dcSApple OSS Distributions 
827*2c2f96dcSApple OSS Distributions 	lck_rw_done(&vsockinfo.all_lock);
828*2c2f96dcSApple OSS Distributions 
829*2c2f96dcSApple OSS Distributions 	if (!error) {
830*2c2f96dcSApple OSS Distributions 		/*
831*2c2f96dcSApple OSS Distributions 		 * Give the user an updated idea of our state.
832*2c2f96dcSApple OSS Distributions 		 * If the generation differs from what we told
833*2c2f96dcSApple OSS Distributions 		 * her before, she knows that something happened
834*2c2f96dcSApple OSS Distributions 		 * while we were processing this request, and it
835*2c2f96dcSApple OSS Distributions 		 * might be necessary to retry.
836*2c2f96dcSApple OSS Distributions 		 */
837*2c2f96dcSApple OSS Distributions 		bzero(&xvg, sizeof(xvg));
838*2c2f96dcSApple OSS Distributions 		xvg.xvg_len = sizeof(xvg);
839*2c2f96dcSApple OSS Distributions 		xvg.xvg_count = n;
840*2c2f96dcSApple OSS Distributions 		xvg.xvg_gen = gen_count;
841*2c2f96dcSApple OSS Distributions 		xvg.xvg_sogen = so_gencnt;
842*2c2f96dcSApple OSS Distributions 		error = SYSCTL_OUT(req, &xvg, sizeof(xvg));
843*2c2f96dcSApple OSS Distributions 	}
844*2c2f96dcSApple OSS Distributions 
845*2c2f96dcSApple OSS Distributions 	return error;
846*2c2f96dcSApple OSS Distributions }
847*2c2f96dcSApple OSS Distributions 
848*2c2f96dcSApple OSS Distributions #ifdef SYSCTL_DECL
849*2c2f96dcSApple OSS Distributions SYSCTL_NODE(_net, OID_AUTO, vsock, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "vsock");
850*2c2f96dcSApple OSS Distributions SYSCTL_UINT(_net_vsock, OID_AUTO, sendspace, CTLFLAG_RW | CTLFLAG_LOCKED,
851*2c2f96dcSApple OSS Distributions     &vsock_sendspace, 0, "Maximum outgoing vsock datagram size");
852*2c2f96dcSApple OSS Distributions SYSCTL_UINT(_net_vsock, OID_AUTO, recvspace, CTLFLAG_RW | CTLFLAG_LOCKED,
853*2c2f96dcSApple OSS Distributions     &vsock_recvspace, 0, "Maximum incoming vsock datagram size");
854*2c2f96dcSApple OSS Distributions SYSCTL_PROC(_net_vsock, OID_AUTO, pcblist,
855*2c2f96dcSApple OSS Distributions     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
856*2c2f96dcSApple OSS Distributions     (caddr_t)(long)SOCK_STREAM, 0, vsock_pcblist, "S,xvsockpcb",
857*2c2f96dcSApple OSS Distributions     "List of active vsock sockets");
858*2c2f96dcSApple OSS Distributions #endif
859*2c2f96dcSApple OSS Distributions 
860*2c2f96dcSApple OSS Distributions /* VSock Protocol */
861*2c2f96dcSApple OSS Distributions 
862*2c2f96dcSApple OSS Distributions static int
vsock_attach(struct socket * so,int proto,struct proc * p)863*2c2f96dcSApple OSS Distributions vsock_attach(struct socket *so, int proto, struct proc *p)
864*2c2f96dcSApple OSS Distributions {
865*2c2f96dcSApple OSS Distributions 	#pragma unused(proto, p)
866*2c2f96dcSApple OSS Distributions 
867*2c2f96dcSApple OSS Distributions 	// Reserve send and receive buffers.
868*2c2f96dcSApple OSS Distributions 	errno_t error = soreserve(so, vsock_sendspace, vsock_recvspace);
869*2c2f96dcSApple OSS Distributions 	if (error) {
870*2c2f96dcSApple OSS Distributions 		return error;
871*2c2f96dcSApple OSS Distributions 	}
872*2c2f96dcSApple OSS Distributions 
873*2c2f96dcSApple OSS Distributions 	// Attach should only be run once per socket.
874*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
875*2c2f96dcSApple OSS Distributions 	if (pcb) {
876*2c2f96dcSApple OSS Distributions 		return EINVAL;
877*2c2f96dcSApple OSS Distributions 	}
878*2c2f96dcSApple OSS Distributions 
879*2c2f96dcSApple OSS Distributions 	// Get the transport for this socket.
880*2c2f96dcSApple OSS Distributions 	struct vsock_transport *transport = os_atomic_load(&the_vsock_transport, relaxed);
881*2c2f96dcSApple OSS Distributions 	if (transport == NULL) {
882*2c2f96dcSApple OSS Distributions 		return ENODEV;
883*2c2f96dcSApple OSS Distributions 	}
884*2c2f96dcSApple OSS Distributions 
885*2c2f96dcSApple OSS Distributions 	// Initialize the vsock protocol control block.
886*2c2f96dcSApple OSS Distributions 	pcb = zalloc_flags(vsockpcb_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
887*2c2f96dcSApple OSS Distributions 	pcb->so = so;
888*2c2f96dcSApple OSS Distributions 	pcb->transport = transport;
889*2c2f96dcSApple OSS Distributions 	pcb->local_address = (struct vsock_address) {
890*2c2f96dcSApple OSS Distributions 		.cid = VMADDR_CID_ANY,
891*2c2f96dcSApple OSS Distributions 		.port = VMADDR_PORT_ANY
892*2c2f96dcSApple OSS Distributions 	};
893*2c2f96dcSApple OSS Distributions 	pcb->remote_address = (struct vsock_address) {
894*2c2f96dcSApple OSS Distributions 		.cid = VMADDR_CID_ANY,
895*2c2f96dcSApple OSS Distributions 		.port = VMADDR_PORT_ANY
896*2c2f96dcSApple OSS Distributions 	};
897*2c2f96dcSApple OSS Distributions 	so->so_pcb = pcb;
898*2c2f96dcSApple OSS Distributions 
899*2c2f96dcSApple OSS Distributions 	// Tell the transport that this socket has attached.
900*2c2f96dcSApple OSS Distributions 	error = transport->attach_socket(transport->provider);
901*2c2f96dcSApple OSS Distributions 	if (error) {
902*2c2f96dcSApple OSS Distributions 		zfree(vsockpcb_zone, pcb);
903*2c2f96dcSApple OSS Distributions 		so->so_pcb = NULL;
904*2c2f96dcSApple OSS Distributions 		return error;
905*2c2f96dcSApple OSS Distributions 	}
906*2c2f96dcSApple OSS Distributions 
907*2c2f96dcSApple OSS Distributions 	// Add to the list of all vsock sockets.
908*2c2f96dcSApple OSS Distributions 	lck_rw_lock_exclusive(&vsockinfo.all_lock);
909*2c2f96dcSApple OSS Distributions 	TAILQ_INSERT_TAIL(&vsockinfo.all, pcb, all);
910*2c2f96dcSApple OSS Distributions 	vsockinfo.all_pcb_count++;
911*2c2f96dcSApple OSS Distributions 	pcb->vsock_gencnt = ++vsockinfo.vsock_gencnt;
912*2c2f96dcSApple OSS Distributions 	lck_rw_done(&vsockinfo.all_lock);
913*2c2f96dcSApple OSS Distributions 
914*2c2f96dcSApple OSS Distributions 	return 0;
915*2c2f96dcSApple OSS Distributions }
916*2c2f96dcSApple OSS Distributions 
917*2c2f96dcSApple OSS Distributions static int
vsock_control(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp,struct proc * p)918*2c2f96dcSApple OSS Distributions vsock_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct proc *p)
919*2c2f96dcSApple OSS Distributions {
920*2c2f96dcSApple OSS Distributions 	#pragma unused(ifp)
921*2c2f96dcSApple OSS Distributions 
922*2c2f96dcSApple OSS Distributions 	VERIFY(so != NULL || p == kernproc);
923*2c2f96dcSApple OSS Distributions 
924*2c2f96dcSApple OSS Distributions 	if (cmd != IOCTL_VM_SOCKETS_GET_LOCAL_CID) {
925*2c2f96dcSApple OSS Distributions 		return EINVAL;
926*2c2f96dcSApple OSS Distributions 	}
927*2c2f96dcSApple OSS Distributions 
928*2c2f96dcSApple OSS Distributions 	struct vsock_transport *transport;
929*2c2f96dcSApple OSS Distributions 	if (so) {
930*2c2f96dcSApple OSS Distributions 		struct vsockpcb *pcb = sotovsockpcb(so);
931*2c2f96dcSApple OSS Distributions 		if (pcb == NULL) {
932*2c2f96dcSApple OSS Distributions 			return EINVAL;
933*2c2f96dcSApple OSS Distributions 		}
934*2c2f96dcSApple OSS Distributions 		transport = pcb->transport;
935*2c2f96dcSApple OSS Distributions 	} else {
936*2c2f96dcSApple OSS Distributions 		transport = os_atomic_load(&the_vsock_transport, relaxed);
937*2c2f96dcSApple OSS Distributions 	}
938*2c2f96dcSApple OSS Distributions 
939*2c2f96dcSApple OSS Distributions 	if (transport == NULL) {
940*2c2f96dcSApple OSS Distributions 		return ENODEV;
941*2c2f96dcSApple OSS Distributions 	}
942*2c2f96dcSApple OSS Distributions 
943*2c2f96dcSApple OSS Distributions 	uint32_t transport_cid;
944*2c2f96dcSApple OSS Distributions 	errno_t error = transport->get_cid(transport->provider, &transport_cid);
945*2c2f96dcSApple OSS Distributions 	if (error) {
946*2c2f96dcSApple OSS Distributions 		return error;
947*2c2f96dcSApple OSS Distributions 	}
948*2c2f96dcSApple OSS Distributions 
949*2c2f96dcSApple OSS Distributions 	memcpy(data, &transport_cid, sizeof(transport_cid));
950*2c2f96dcSApple OSS Distributions 
951*2c2f96dcSApple OSS Distributions 	return 0;
952*2c2f96dcSApple OSS Distributions }
953*2c2f96dcSApple OSS Distributions 
954*2c2f96dcSApple OSS Distributions static int
vsock_detach(struct socket * so)955*2c2f96dcSApple OSS Distributions vsock_detach(struct socket *so)
956*2c2f96dcSApple OSS Distributions {
957*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
958*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
959*2c2f96dcSApple OSS Distributions 		return EINVAL;
960*2c2f96dcSApple OSS Distributions 	}
961*2c2f96dcSApple OSS Distributions 
962*2c2f96dcSApple OSS Distributions 	vsock_unbind_pcb(pcb);
963*2c2f96dcSApple OSS Distributions 
964*2c2f96dcSApple OSS Distributions 	// Tell the transport that this socket has detached.
965*2c2f96dcSApple OSS Distributions 	struct vsock_transport *transport = pcb->transport;
966*2c2f96dcSApple OSS Distributions 	errno_t error = transport->detach_socket(transport->provider);
967*2c2f96dcSApple OSS Distributions 	if (error) {
968*2c2f96dcSApple OSS Distributions 		return error;
969*2c2f96dcSApple OSS Distributions 	}
970*2c2f96dcSApple OSS Distributions 
971*2c2f96dcSApple OSS Distributions 	// Remove from the list of all vsock sockets.
972*2c2f96dcSApple OSS Distributions 	lck_rw_lock_exclusive(&vsockinfo.all_lock);
973*2c2f96dcSApple OSS Distributions 	TAILQ_REMOVE(&vsockinfo.all, pcb, all);
974*2c2f96dcSApple OSS Distributions 	pcb->all.tqe_next = NULL;
975*2c2f96dcSApple OSS Distributions 	pcb->all.tqe_prev = NULL;
976*2c2f96dcSApple OSS Distributions 	vsockinfo.all_pcb_count--;
977*2c2f96dcSApple OSS Distributions 	vsockinfo.vsock_gencnt++;
978*2c2f96dcSApple OSS Distributions 	lck_rw_done(&vsockinfo.all_lock);
979*2c2f96dcSApple OSS Distributions 
980*2c2f96dcSApple OSS Distributions 	// Mark this socket for deallocation.
981*2c2f96dcSApple OSS Distributions 	so->so_flags |= SOF_PCBCLEARING;
982*2c2f96dcSApple OSS Distributions 
983*2c2f96dcSApple OSS Distributions 	return 0;
984*2c2f96dcSApple OSS Distributions }
985*2c2f96dcSApple OSS Distributions 
986*2c2f96dcSApple OSS Distributions static int
vsock_abort(struct socket * so)987*2c2f96dcSApple OSS Distributions vsock_abort(struct socket *so)
988*2c2f96dcSApple OSS Distributions {
989*2c2f96dcSApple OSS Distributions 	return vsock_detach(so);
990*2c2f96dcSApple OSS Distributions }
991*2c2f96dcSApple OSS Distributions 
992*2c2f96dcSApple OSS Distributions static int
vsock_bind(struct socket * so,struct sockaddr * nam,struct proc * p)993*2c2f96dcSApple OSS Distributions vsock_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
994*2c2f96dcSApple OSS Distributions {
995*2c2f96dcSApple OSS Distributions 	#pragma unused(p)
996*2c2f96dcSApple OSS Distributions 
997*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
998*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
999*2c2f96dcSApple OSS Distributions 		return EINVAL;
1000*2c2f96dcSApple OSS Distributions 	}
1001*2c2f96dcSApple OSS Distributions 
1002*2c2f96dcSApple OSS Distributions 	struct sockaddr_vm *addr = (struct sockaddr_vm *)nam;
1003*2c2f96dcSApple OSS Distributions 
1004*2c2f96dcSApple OSS Distributions 	errno_t error = vsock_sockaddr_vm_validate(pcb, addr);
1005*2c2f96dcSApple OSS Distributions 	if (error) {
1006*2c2f96dcSApple OSS Distributions 		return error;
1007*2c2f96dcSApple OSS Distributions 	}
1008*2c2f96dcSApple OSS Distributions 
1009*2c2f96dcSApple OSS Distributions 	struct vsock_address laddr = (struct vsock_address) {
1010*2c2f96dcSApple OSS Distributions 		.cid = addr->svm_cid,
1011*2c2f96dcSApple OSS Distributions 		.port = addr->svm_port,
1012*2c2f96dcSApple OSS Distributions 	};
1013*2c2f96dcSApple OSS Distributions 
1014*2c2f96dcSApple OSS Distributions 	struct vsock_address raddr = (struct vsock_address) {
1015*2c2f96dcSApple OSS Distributions 		.cid = VMADDR_CID_ANY,
1016*2c2f96dcSApple OSS Distributions 		.port = VMADDR_PORT_ANY,
1017*2c2f96dcSApple OSS Distributions 	};
1018*2c2f96dcSApple OSS Distributions 
1019*2c2f96dcSApple OSS Distributions 	error = vsock_bind_address(pcb, laddr, raddr);
1020*2c2f96dcSApple OSS Distributions 	if (error) {
1021*2c2f96dcSApple OSS Distributions 		return error;
1022*2c2f96dcSApple OSS Distributions 	}
1023*2c2f96dcSApple OSS Distributions 
1024*2c2f96dcSApple OSS Distributions 	return 0;
1025*2c2f96dcSApple OSS Distributions }
1026*2c2f96dcSApple OSS Distributions 
1027*2c2f96dcSApple OSS Distributions static int
vsock_listen(struct socket * so,struct proc * p)1028*2c2f96dcSApple OSS Distributions vsock_listen(struct socket *so, struct proc *p)
1029*2c2f96dcSApple OSS Distributions {
1030*2c2f96dcSApple OSS Distributions 	#pragma unused(p)
1031*2c2f96dcSApple OSS Distributions 
1032*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1033*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1034*2c2f96dcSApple OSS Distributions 		return EINVAL;
1035*2c2f96dcSApple OSS Distributions 	}
1036*2c2f96dcSApple OSS Distributions 
1037*2c2f96dcSApple OSS Distributions 	// Only stream is supported currently.
1038*2c2f96dcSApple OSS Distributions 	if (so->so_type != SOCK_STREAM) {
1039*2c2f96dcSApple OSS Distributions 		return EAFNOSUPPORT;
1040*2c2f96dcSApple OSS Distributions 	}
1041*2c2f96dcSApple OSS Distributions 
1042*2c2f96dcSApple OSS Distributions 	struct vsock_address *addr = &pcb->local_address;
1043*2c2f96dcSApple OSS Distributions 
1044*2c2f96dcSApple OSS Distributions 	if (addr->port == VMADDR_CID_ANY) {
1045*2c2f96dcSApple OSS Distributions 		return EFAULT;
1046*2c2f96dcSApple OSS Distributions 	}
1047*2c2f96dcSApple OSS Distributions 
1048*2c2f96dcSApple OSS Distributions 	struct vsock_transport *transport = pcb->transport;
1049*2c2f96dcSApple OSS Distributions 	uint32_t transport_cid;
1050*2c2f96dcSApple OSS Distributions 	errno_t error = transport->get_cid(transport->provider, &transport_cid);
1051*2c2f96dcSApple OSS Distributions 	if (error) {
1052*2c2f96dcSApple OSS Distributions 		return error;
1053*2c2f96dcSApple OSS Distributions 	}
1054*2c2f96dcSApple OSS Distributions 
1055*2c2f96dcSApple OSS Distributions 	// Can listen on the transport's cid or any.
1056*2c2f96dcSApple OSS Distributions 	if (addr->cid != transport_cid && addr->cid != VMADDR_CID_ANY) {
1057*2c2f96dcSApple OSS Distributions 		return EFAULT;
1058*2c2f96dcSApple OSS Distributions 	}
1059*2c2f96dcSApple OSS Distributions 
1060*2c2f96dcSApple OSS Distributions 	return 0;
1061*2c2f96dcSApple OSS Distributions }
1062*2c2f96dcSApple OSS Distributions 
1063*2c2f96dcSApple OSS Distributions static int
vsock_accept(struct socket * so,struct sockaddr ** nam)1064*2c2f96dcSApple OSS Distributions vsock_accept(struct socket *so, struct sockaddr **nam)
1065*2c2f96dcSApple OSS Distributions {
1066*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1067*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1068*2c2f96dcSApple OSS Distributions 		return EINVAL;
1069*2c2f96dcSApple OSS Distributions 	}
1070*2c2f96dcSApple OSS Distributions 
1071*2c2f96dcSApple OSS Distributions 	// Do not accept disconnected sockets.
1072*2c2f96dcSApple OSS Distributions 	if (so->so_state & SS_ISDISCONNECTED) {
1073*2c2f96dcSApple OSS Distributions 		return ECONNABORTED;
1074*2c2f96dcSApple OSS Distributions 	}
1075*2c2f96dcSApple OSS Distributions 
1076*2c2f96dcSApple OSS Distributions 	*nam = vsock_new_sockaddr(&pcb->remote_address);
1077*2c2f96dcSApple OSS Distributions 
1078*2c2f96dcSApple OSS Distributions 	return 0;
1079*2c2f96dcSApple OSS Distributions }
1080*2c2f96dcSApple OSS Distributions 
1081*2c2f96dcSApple OSS Distributions static int
vsock_connect(struct socket * so,struct sockaddr * nam,struct proc * p)1082*2c2f96dcSApple OSS Distributions vsock_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
1083*2c2f96dcSApple OSS Distributions {
1084*2c2f96dcSApple OSS Distributions 	#pragma unused(p)
1085*2c2f96dcSApple OSS Distributions 
1086*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1087*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1088*2c2f96dcSApple OSS Distributions 		return EINVAL;
1089*2c2f96dcSApple OSS Distributions 	}
1090*2c2f96dcSApple OSS Distributions 
1091*2c2f96dcSApple OSS Distributions 	struct sockaddr_vm *addr = (struct sockaddr_vm *)nam;
1092*2c2f96dcSApple OSS Distributions 
1093*2c2f96dcSApple OSS Distributions 	errno_t error = vsock_sockaddr_vm_validate(pcb, addr);
1094*2c2f96dcSApple OSS Distributions 	if (error) {
1095*2c2f96dcSApple OSS Distributions 		return error;
1096*2c2f96dcSApple OSS Distributions 	}
1097*2c2f96dcSApple OSS Distributions 
1098*2c2f96dcSApple OSS Distributions 	uint32_t transport_cid;
1099*2c2f96dcSApple OSS Distributions 	struct vsock_transport *transport = pcb->transport;
1100*2c2f96dcSApple OSS Distributions 	error = transport->get_cid(transport->provider, &transport_cid);
1101*2c2f96dcSApple OSS Distributions 	if (error) {
1102*2c2f96dcSApple OSS Distributions 		return error;
1103*2c2f96dcSApple OSS Distributions 	}
1104*2c2f96dcSApple OSS Distributions 
1105*2c2f96dcSApple OSS Distributions 	// Only supporting connections to the host, hypervisor, or self for now.
1106*2c2f96dcSApple OSS Distributions 	if (addr->svm_cid != VMADDR_CID_HOST &&
1107*2c2f96dcSApple OSS Distributions 	    addr->svm_cid != VMADDR_CID_HYPERVISOR &&
1108*2c2f96dcSApple OSS Distributions 	    addr->svm_cid != transport_cid) {
1109*2c2f96dcSApple OSS Distributions 		return EFAULT;
1110*2c2f96dcSApple OSS Distributions 	}
1111*2c2f96dcSApple OSS Distributions 
1112*2c2f96dcSApple OSS Distributions 	soisconnecting(so);
1113*2c2f96dcSApple OSS Distributions 
1114*2c2f96dcSApple OSS Distributions 	// Set the remote and local address.
1115*2c2f96dcSApple OSS Distributions 	struct vsock_address remote_addr = (struct vsock_address) {
1116*2c2f96dcSApple OSS Distributions 		.cid = addr->svm_cid,
1117*2c2f96dcSApple OSS Distributions 		.port = addr->svm_port,
1118*2c2f96dcSApple OSS Distributions 	};
1119*2c2f96dcSApple OSS Distributions 
1120*2c2f96dcSApple OSS Distributions 	struct vsock_address local_addr = (struct vsock_address) {
1121*2c2f96dcSApple OSS Distributions 		.cid = transport_cid,
1122*2c2f96dcSApple OSS Distributions 		.port = VMADDR_PORT_ANY,
1123*2c2f96dcSApple OSS Distributions 	};
1124*2c2f96dcSApple OSS Distributions 
1125*2c2f96dcSApple OSS Distributions 	// Bind to the address.
1126*2c2f96dcSApple OSS Distributions 	error = vsock_bind_address(pcb, local_addr, remote_addr);
1127*2c2f96dcSApple OSS Distributions 	if (error) {
1128*2c2f96dcSApple OSS Distributions 		goto cleanup;
1129*2c2f96dcSApple OSS Distributions 	}
1130*2c2f96dcSApple OSS Distributions 
1131*2c2f96dcSApple OSS Distributions 	// Attempt a connection using the socket's transport.
1132*2c2f96dcSApple OSS Distributions 	error = vsock_pcb_connect(pcb);
1133*2c2f96dcSApple OSS Distributions 	if (error) {
1134*2c2f96dcSApple OSS Distributions 		goto cleanup;
1135*2c2f96dcSApple OSS Distributions 	}
1136*2c2f96dcSApple OSS Distributions 
1137*2c2f96dcSApple OSS Distributions 	if ((so->so_state & SS_ISCONNECTED) == 0) {
1138*2c2f96dcSApple OSS Distributions 		// Don't wait for peer's response if non-blocking.
1139*2c2f96dcSApple OSS Distributions 		if (so->so_state & SS_NBIO) {
1140*2c2f96dcSApple OSS Distributions 			error = EINPROGRESS;
1141*2c2f96dcSApple OSS Distributions 			goto done;
1142*2c2f96dcSApple OSS Distributions 		}
1143*2c2f96dcSApple OSS Distributions 
1144*2c2f96dcSApple OSS Distributions 		struct timespec ts = (struct timespec) {
1145*2c2f96dcSApple OSS Distributions 			.tv_sec = so->so_snd.sb_timeo.tv_sec,
1146*2c2f96dcSApple OSS Distributions 			.tv_nsec = so->so_snd.sb_timeo.tv_usec * 1000,
1147*2c2f96dcSApple OSS Distributions 		};
1148*2c2f96dcSApple OSS Distributions 
1149*2c2f96dcSApple OSS Distributions 		lck_mtx_t *mutex_held;
1150*2c2f96dcSApple OSS Distributions 		if (so->so_proto->pr_getlock != NULL) {
1151*2c2f96dcSApple OSS Distributions 			mutex_held = (*so->so_proto->pr_getlock)(so, PR_F_WILLUNLOCK);
1152*2c2f96dcSApple OSS Distributions 		} else {
1153*2c2f96dcSApple OSS Distributions 			mutex_held = so->so_proto->pr_domain->dom_mtx;
1154*2c2f96dcSApple OSS Distributions 		}
1155*2c2f96dcSApple OSS Distributions 
1156*2c2f96dcSApple OSS Distributions 		// Wait until we receive a response to the connect request.
1157*2c2f96dcSApple OSS Distributions 		error = msleep((caddr_t)&so->so_timeo, mutex_held, PSOCK | PCATCH, "vsock_connect", &ts);
1158*2c2f96dcSApple OSS Distributions 		if (error) {
1159*2c2f96dcSApple OSS Distributions 			if (error == EAGAIN) {
1160*2c2f96dcSApple OSS Distributions 				error = ETIMEDOUT;
1161*2c2f96dcSApple OSS Distributions 			}
1162*2c2f96dcSApple OSS Distributions 			goto cleanup;
1163*2c2f96dcSApple OSS Distributions 		}
1164*2c2f96dcSApple OSS Distributions 	}
1165*2c2f96dcSApple OSS Distributions 
1166*2c2f96dcSApple OSS Distributions cleanup:
1167*2c2f96dcSApple OSS Distributions 	if (so->so_error && !error) {
1168*2c2f96dcSApple OSS Distributions 		error = so->so_error;
1169*2c2f96dcSApple OSS Distributions 		so->so_error = 0;
1170*2c2f96dcSApple OSS Distributions 	}
1171*2c2f96dcSApple OSS Distributions 	if (!error) {
1172*2c2f96dcSApple OSS Distributions 		error = !(so->so_state & SS_ISCONNECTED);
1173*2c2f96dcSApple OSS Distributions 	}
1174*2c2f96dcSApple OSS Distributions 	if (error) {
1175*2c2f96dcSApple OSS Distributions 		vsock_unbind_pcb(pcb);
1176*2c2f96dcSApple OSS Distributions 	}
1177*2c2f96dcSApple OSS Distributions 
1178*2c2f96dcSApple OSS Distributions done:
1179*2c2f96dcSApple OSS Distributions 	return error;
1180*2c2f96dcSApple OSS Distributions }
1181*2c2f96dcSApple OSS Distributions 
1182*2c2f96dcSApple OSS Distributions static int
vsock_disconnect(struct socket * so)1183*2c2f96dcSApple OSS Distributions vsock_disconnect(struct socket *so)
1184*2c2f96dcSApple OSS Distributions {
1185*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1186*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1187*2c2f96dcSApple OSS Distributions 		return EINVAL;
1188*2c2f96dcSApple OSS Distributions 	}
1189*2c2f96dcSApple OSS Distributions 
1190*2c2f96dcSApple OSS Distributions 	return vsock_disconnect_pcb(pcb);
1191*2c2f96dcSApple OSS Distributions }
1192*2c2f96dcSApple OSS Distributions 
1193*2c2f96dcSApple OSS Distributions static int
vsock_sockaddr(struct socket * so,struct sockaddr ** nam)1194*2c2f96dcSApple OSS Distributions vsock_sockaddr(struct socket *so, struct sockaddr **nam)
1195*2c2f96dcSApple OSS Distributions {
1196*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1197*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1198*2c2f96dcSApple OSS Distributions 		return EINVAL;
1199*2c2f96dcSApple OSS Distributions 	}
1200*2c2f96dcSApple OSS Distributions 
1201*2c2f96dcSApple OSS Distributions 	*nam = vsock_new_sockaddr(&pcb->local_address);
1202*2c2f96dcSApple OSS Distributions 
1203*2c2f96dcSApple OSS Distributions 	return 0;
1204*2c2f96dcSApple OSS Distributions }
1205*2c2f96dcSApple OSS Distributions 
1206*2c2f96dcSApple OSS Distributions static int
vsock_peeraddr(struct socket * so,struct sockaddr ** nam)1207*2c2f96dcSApple OSS Distributions vsock_peeraddr(struct socket *so, struct sockaddr **nam)
1208*2c2f96dcSApple OSS Distributions {
1209*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1210*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1211*2c2f96dcSApple OSS Distributions 		return EINVAL;
1212*2c2f96dcSApple OSS Distributions 	}
1213*2c2f96dcSApple OSS Distributions 
1214*2c2f96dcSApple OSS Distributions 	*nam = vsock_new_sockaddr(&pcb->remote_address);
1215*2c2f96dcSApple OSS Distributions 
1216*2c2f96dcSApple OSS Distributions 	return 0;
1217*2c2f96dcSApple OSS Distributions }
1218*2c2f96dcSApple OSS Distributions 
1219*2c2f96dcSApple OSS Distributions static int
vsock_send(struct socket * so,int flags,struct mbuf * m,struct sockaddr * nam,struct mbuf * control,proc_t p)1220*2c2f96dcSApple OSS Distributions vsock_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, proc_t p)
1221*2c2f96dcSApple OSS Distributions {
1222*2c2f96dcSApple OSS Distributions 	#pragma unused(flags, nam, p)
1223*2c2f96dcSApple OSS Distributions 
1224*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1225*2c2f96dcSApple OSS Distributions 	if (pcb == NULL || m == NULL) {
1226*2c2f96dcSApple OSS Distributions 		return EINVAL;
1227*2c2f96dcSApple OSS Distributions 	}
1228*2c2f96dcSApple OSS Distributions 
1229*2c2f96dcSApple OSS Distributions 	if (control != NULL) {
1230*2c2f96dcSApple OSS Distributions 		m_freem(control);
1231*2c2f96dcSApple OSS Distributions 		return EOPNOTSUPP;
1232*2c2f96dcSApple OSS Distributions 	}
1233*2c2f96dcSApple OSS Distributions 
1234*2c2f96dcSApple OSS Distributions 	// Ensure this socket is connected.
1235*2c2f96dcSApple OSS Distributions 	if ((so->so_state & SS_ISCONNECTED) == 0) {
1236*2c2f96dcSApple OSS Distributions 		if (m != NULL) {
1237*2c2f96dcSApple OSS Distributions 			mbuf_freem_list(m);
1238*2c2f96dcSApple OSS Distributions 		}
1239*2c2f96dcSApple OSS Distributions 		return EPERM;
1240*2c2f96dcSApple OSS Distributions 	}
1241*2c2f96dcSApple OSS Distributions 
1242*2c2f96dcSApple OSS Distributions 	errno_t error;
1243*2c2f96dcSApple OSS Distributions 
1244*2c2f96dcSApple OSS Distributions 	// rdar://84098487 (SEED: Web: Virtio-socket sent data lost after 128KB)
1245*2c2f96dcSApple OSS Distributions 	// For writes larger than the default `sosendmaxchain` of 65536, vsock_send() is called multiple times per write().
1246*2c2f96dcSApple OSS Distributions 	// Only the first call to vsock_send() is passed a valid mbuf packet, while subsequent calls are not marked as a packet
1247*2c2f96dcSApple OSS Distributions 	// with a valid length. We should mark all mbufs as a packet and set the correct packet length so that the downstream
1248*2c2f96dcSApple OSS Distributions 	// socket transport layer can correctly generate physical segments.
1249*2c2f96dcSApple OSS Distributions 	if (!(mbuf_flags(m) & MBUF_PKTHDR)) {
1250*2c2f96dcSApple OSS Distributions 		if (!(mbuf_flags(m) & M_EXT)) {
1251*2c2f96dcSApple OSS Distributions 			struct mbuf *header = NULL;
1252*2c2f96dcSApple OSS Distributions 			MGETHDR(header, M_WAITOK, MT_HEADER);
1253*2c2f96dcSApple OSS Distributions 			if (header == NULL) {
1254*2c2f96dcSApple OSS Distributions 				if (m != NULL) {
1255*2c2f96dcSApple OSS Distributions 					mbuf_freem_list(m);
1256*2c2f96dcSApple OSS Distributions 				}
1257*2c2f96dcSApple OSS Distributions 				return ENOBUFS;
1258*2c2f96dcSApple OSS Distributions 			}
1259*2c2f96dcSApple OSS Distributions 			header->m_next = m;
1260*2c2f96dcSApple OSS Distributions 			m = header;
1261*2c2f96dcSApple OSS Distributions 		} else {
1262*2c2f96dcSApple OSS Distributions 			mbuf_setflags(m, mbuf_flags(m) | MBUF_PKTHDR);
1263*2c2f96dcSApple OSS Distributions 		}
1264*2c2f96dcSApple OSS Distributions 
1265*2c2f96dcSApple OSS Distributions 		size_t len = 0;
1266*2c2f96dcSApple OSS Distributions 		struct mbuf *next = m;
1267*2c2f96dcSApple OSS Distributions 		while (next) {
1268*2c2f96dcSApple OSS Distributions 			len += mbuf_len(next);
1269*2c2f96dcSApple OSS Distributions 			next = mbuf_next(next);
1270*2c2f96dcSApple OSS Distributions 		}
1271*2c2f96dcSApple OSS Distributions 		mbuf_pkthdr_setlen(m, len);
1272*2c2f96dcSApple OSS Distributions 	}
1273*2c2f96dcSApple OSS Distributions 
1274*2c2f96dcSApple OSS Distributions 	const size_t len = mbuf_pkthdr_len(m);
1275*2c2f96dcSApple OSS Distributions 	uint32_t free_space = vsock_get_peer_space(pcb);
1276*2c2f96dcSApple OSS Distributions 
1277*2c2f96dcSApple OSS Distributions 	// Ensure the peer has enough space in their receive buffer.
1278*2c2f96dcSApple OSS Distributions 	while (len > free_space) {
1279*2c2f96dcSApple OSS Distributions 		// Record the number of free peer bytes necessary before we can send.
1280*2c2f96dcSApple OSS Distributions 		if (len > pcb->waiting_send_size) {
1281*2c2f96dcSApple OSS Distributions 			pcb->waiting_send_size = len;
1282*2c2f96dcSApple OSS Distributions 		}
1283*2c2f96dcSApple OSS Distributions 
1284*2c2f96dcSApple OSS Distributions 		// Send a credit request.
1285*2c2f96dcSApple OSS Distributions 		error = vsock_pcb_credit_request(pcb);
1286*2c2f96dcSApple OSS Distributions 		if (error) {
1287*2c2f96dcSApple OSS Distributions 			if (m != NULL) {
1288*2c2f96dcSApple OSS Distributions 				mbuf_freem_list(m);
1289*2c2f96dcSApple OSS Distributions 			}
1290*2c2f96dcSApple OSS Distributions 			return error;
1291*2c2f96dcSApple OSS Distributions 		}
1292*2c2f96dcSApple OSS Distributions 
1293*2c2f96dcSApple OSS Distributions 		// Check again in case free space was automatically updated in loopback case.
1294*2c2f96dcSApple OSS Distributions 		free_space = vsock_get_peer_space(pcb);
1295*2c2f96dcSApple OSS Distributions 		if (len <= free_space) {
1296*2c2f96dcSApple OSS Distributions 			pcb->waiting_send_size = 0;
1297*2c2f96dcSApple OSS Distributions 			break;
1298*2c2f96dcSApple OSS Distributions 		}
1299*2c2f96dcSApple OSS Distributions 
1300*2c2f96dcSApple OSS Distributions 		// Bail if this is a non-blocking socket.
1301*2c2f96dcSApple OSS Distributions 		if (so->so_state & SS_NBIO) {
1302*2c2f96dcSApple OSS Distributions 			if (m != NULL) {
1303*2c2f96dcSApple OSS Distributions 				mbuf_freem_list(m);
1304*2c2f96dcSApple OSS Distributions 			}
1305*2c2f96dcSApple OSS Distributions 			return EWOULDBLOCK;
1306*2c2f96dcSApple OSS Distributions 		}
1307*2c2f96dcSApple OSS Distributions 
1308*2c2f96dcSApple OSS Distributions 		// Wait until our peer has enough free space in their receive buffer.
1309*2c2f96dcSApple OSS Distributions 		error = sbwait(&so->so_snd);
1310*2c2f96dcSApple OSS Distributions 		pcb->waiting_send_size = 0;
1311*2c2f96dcSApple OSS Distributions 		if (error) {
1312*2c2f96dcSApple OSS Distributions 			if (m != NULL) {
1313*2c2f96dcSApple OSS Distributions 				mbuf_freem_list(m);
1314*2c2f96dcSApple OSS Distributions 			}
1315*2c2f96dcSApple OSS Distributions 			return error;
1316*2c2f96dcSApple OSS Distributions 		}
1317*2c2f96dcSApple OSS Distributions 
1318*2c2f96dcSApple OSS Distributions 		// Bail if an error occured or we can't send more.
1319*2c2f96dcSApple OSS Distributions 		if (so->so_state & SS_CANTSENDMORE) {
1320*2c2f96dcSApple OSS Distributions 			if (m != NULL) {
1321*2c2f96dcSApple OSS Distributions 				mbuf_freem_list(m);
1322*2c2f96dcSApple OSS Distributions 			}
1323*2c2f96dcSApple OSS Distributions 			return EPIPE;
1324*2c2f96dcSApple OSS Distributions 		} else if (so->so_error) {
1325*2c2f96dcSApple OSS Distributions 			error = so->so_error;
1326*2c2f96dcSApple OSS Distributions 			so->so_error = 0;
1327*2c2f96dcSApple OSS Distributions 			if (m != NULL) {
1328*2c2f96dcSApple OSS Distributions 				mbuf_freem_list(m);
1329*2c2f96dcSApple OSS Distributions 			}
1330*2c2f96dcSApple OSS Distributions 			return error;
1331*2c2f96dcSApple OSS Distributions 		}
1332*2c2f96dcSApple OSS Distributions 
1333*2c2f96dcSApple OSS Distributions 		free_space = vsock_get_peer_space(pcb);
1334*2c2f96dcSApple OSS Distributions 	}
1335*2c2f96dcSApple OSS Distributions 
1336*2c2f96dcSApple OSS Distributions 	// Send a payload over the transport.
1337*2c2f96dcSApple OSS Distributions 	error = vsock_pcb_send(pcb, m);
1338*2c2f96dcSApple OSS Distributions 	if (error) {
1339*2c2f96dcSApple OSS Distributions 		return error;
1340*2c2f96dcSApple OSS Distributions 	}
1341*2c2f96dcSApple OSS Distributions 
1342*2c2f96dcSApple OSS Distributions 	pcb->tx_cnt += len;
1343*2c2f96dcSApple OSS Distributions 
1344*2c2f96dcSApple OSS Distributions 	return 0;
1345*2c2f96dcSApple OSS Distributions }
1346*2c2f96dcSApple OSS Distributions 
1347*2c2f96dcSApple OSS Distributions static int
vsock_shutdown(struct socket * so)1348*2c2f96dcSApple OSS Distributions vsock_shutdown(struct socket *so)
1349*2c2f96dcSApple OSS Distributions {
1350*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1351*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1352*2c2f96dcSApple OSS Distributions 		return EINVAL;
1353*2c2f96dcSApple OSS Distributions 	}
1354*2c2f96dcSApple OSS Distributions 
1355*2c2f96dcSApple OSS Distributions 	socantsendmore(so);
1356*2c2f96dcSApple OSS Distributions 
1357*2c2f96dcSApple OSS Distributions 	// Tell peer we will no longer send.
1358*2c2f96dcSApple OSS Distributions 	errno_t error = vsock_pcb_shutdown_send(pcb);
1359*2c2f96dcSApple OSS Distributions 	if (error) {
1360*2c2f96dcSApple OSS Distributions 		return error;
1361*2c2f96dcSApple OSS Distributions 	}
1362*2c2f96dcSApple OSS Distributions 
1363*2c2f96dcSApple OSS Distributions 	return 0;
1364*2c2f96dcSApple OSS Distributions }
1365*2c2f96dcSApple OSS Distributions 
1366*2c2f96dcSApple OSS Distributions static int
vsock_soreceive(struct socket * so,struct sockaddr ** psa,struct uio * uio,struct mbuf ** mp0,struct mbuf ** controlp,int * flagsp)1367*2c2f96dcSApple OSS Distributions vsock_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
1368*2c2f96dcSApple OSS Distributions     struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
1369*2c2f96dcSApple OSS Distributions {
1370*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1371*2c2f96dcSApple OSS Distributions 	if (pcb == NULL) {
1372*2c2f96dcSApple OSS Distributions 		return EINVAL;
1373*2c2f96dcSApple OSS Distributions 	}
1374*2c2f96dcSApple OSS Distributions 
1375*2c2f96dcSApple OSS Distributions 	user_ssize_t length = uio_resid(uio);
1376*2c2f96dcSApple OSS Distributions 	int result = soreceive(so, psa, uio, mp0, controlp, flagsp);
1377*2c2f96dcSApple OSS Distributions 	length -= uio_resid(uio);
1378*2c2f96dcSApple OSS Distributions 
1379*2c2f96dcSApple OSS Distributions 	socket_lock(so, 1);
1380*2c2f96dcSApple OSS Distributions 
1381*2c2f96dcSApple OSS Distributions 	pcb->fwd_cnt += length;
1382*2c2f96dcSApple OSS Distributions 
1383*2c2f96dcSApple OSS Distributions 	const uint32_t threshold = VSOCK_MAX_PACKET_SIZE;
1384*2c2f96dcSApple OSS Distributions 
1385*2c2f96dcSApple OSS Distributions 	// Send a credit update if is possible that the peer will no longer send.
1386*2c2f96dcSApple OSS Distributions 	if ((pcb->fwd_cnt - pcb->last_fwd_cnt + threshold) >= pcb->last_buf_alloc) {
1387*2c2f96dcSApple OSS Distributions 		errno_t error = vsock_pcb_credit_update(pcb);
1388*2c2f96dcSApple OSS Distributions 		if (!result && error) {
1389*2c2f96dcSApple OSS Distributions 			result = error;
1390*2c2f96dcSApple OSS Distributions 		}
1391*2c2f96dcSApple OSS Distributions 	}
1392*2c2f96dcSApple OSS Distributions 
1393*2c2f96dcSApple OSS Distributions 	socket_unlock(so, 1);
1394*2c2f96dcSApple OSS Distributions 
1395*2c2f96dcSApple OSS Distributions 	return result;
1396*2c2f96dcSApple OSS Distributions }
1397*2c2f96dcSApple OSS Distributions 
1398*2c2f96dcSApple OSS Distributions static struct pr_usrreqs vsock_usrreqs = {
1399*2c2f96dcSApple OSS Distributions 	.pru_abort =            vsock_abort,
1400*2c2f96dcSApple OSS Distributions 	.pru_attach =           vsock_attach,
1401*2c2f96dcSApple OSS Distributions 	.pru_control =          vsock_control,
1402*2c2f96dcSApple OSS Distributions 	.pru_detach =           vsock_detach,
1403*2c2f96dcSApple OSS Distributions 	.pru_bind =             vsock_bind,
1404*2c2f96dcSApple OSS Distributions 	.pru_listen =           vsock_listen,
1405*2c2f96dcSApple OSS Distributions 	.pru_accept =           vsock_accept,
1406*2c2f96dcSApple OSS Distributions 	.pru_connect =          vsock_connect,
1407*2c2f96dcSApple OSS Distributions 	.pru_disconnect =       vsock_disconnect,
1408*2c2f96dcSApple OSS Distributions 	.pru_send =             vsock_send,
1409*2c2f96dcSApple OSS Distributions 	.pru_shutdown =         vsock_shutdown,
1410*2c2f96dcSApple OSS Distributions 	.pru_sockaddr =         vsock_sockaddr,
1411*2c2f96dcSApple OSS Distributions 	.pru_peeraddr =         vsock_peeraddr,
1412*2c2f96dcSApple OSS Distributions 	.pru_sosend =           sosend,
1413*2c2f96dcSApple OSS Distributions 	.pru_soreceive =        vsock_soreceive,
1414*2c2f96dcSApple OSS Distributions };
1415*2c2f96dcSApple OSS Distributions 
1416*2c2f96dcSApple OSS Distributions static void
vsock_init(struct protosw * pp,struct domain * dp)1417*2c2f96dcSApple OSS Distributions vsock_init(struct protosw *pp, struct domain *dp)
1418*2c2f96dcSApple OSS Distributions {
1419*2c2f96dcSApple OSS Distributions 	#pragma unused(dp)
1420*2c2f96dcSApple OSS Distributions 
1421*2c2f96dcSApple OSS Distributions 	static int vsock_initialized = 0;
1422*2c2f96dcSApple OSS Distributions 	VERIFY((pp->pr_flags & (PR_INITIALIZED | PR_ATTACHED)) == PR_ATTACHED);
1423*2c2f96dcSApple OSS Distributions 	if (!os_atomic_cmpxchg((volatile int *)&vsock_initialized, 0, 1, acq_rel)) {
1424*2c2f96dcSApple OSS Distributions 		return;
1425*2c2f96dcSApple OSS Distributions 	}
1426*2c2f96dcSApple OSS Distributions 
1427*2c2f96dcSApple OSS Distributions 	// Setup VSock protocol info struct.
1428*2c2f96dcSApple OSS Distributions 	lck_rw_init(&vsockinfo.all_lock, &vsock_lock_grp, LCK_ATTR_NULL);
1429*2c2f96dcSApple OSS Distributions 	lck_rw_init(&vsockinfo.bound_lock, &vsock_lock_grp, LCK_ATTR_NULL);
1430*2c2f96dcSApple OSS Distributions 	lck_mtx_init(&vsockinfo.port_lock, &vsock_lock_grp, LCK_ATTR_NULL);
1431*2c2f96dcSApple OSS Distributions 	TAILQ_INIT(&vsockinfo.all);
1432*2c2f96dcSApple OSS Distributions 	LIST_INIT(&vsockinfo.bound);
1433*2c2f96dcSApple OSS Distributions 	vsockinfo.last_port = VMADDR_PORT_ANY;
1434*2c2f96dcSApple OSS Distributions }
1435*2c2f96dcSApple OSS Distributions 
1436*2c2f96dcSApple OSS Distributions static int
vsock_sofreelastref(struct socket * so,int dealloc)1437*2c2f96dcSApple OSS Distributions vsock_sofreelastref(struct socket *so, int dealloc)
1438*2c2f96dcSApple OSS Distributions {
1439*2c2f96dcSApple OSS Distributions 	socket_lock_assert_owned(so);
1440*2c2f96dcSApple OSS Distributions 
1441*2c2f96dcSApple OSS Distributions 	struct vsockpcb *pcb = sotovsockpcb(so);
1442*2c2f96dcSApple OSS Distributions 	if (pcb != NULL) {
1443*2c2f96dcSApple OSS Distributions 		zfree(vsockpcb_zone, pcb);
1444*2c2f96dcSApple OSS Distributions 	}
1445*2c2f96dcSApple OSS Distributions 
1446*2c2f96dcSApple OSS Distributions 	so->so_pcb = NULL;
1447*2c2f96dcSApple OSS Distributions 	sofreelastref(so, dealloc);
1448*2c2f96dcSApple OSS Distributions 
1449*2c2f96dcSApple OSS Distributions 	return 0;
1450*2c2f96dcSApple OSS Distributions }
1451*2c2f96dcSApple OSS Distributions 
1452*2c2f96dcSApple OSS Distributions static int
vsock_unlock(struct socket * so,int refcount,void * lr_saved)1453*2c2f96dcSApple OSS Distributions vsock_unlock(struct socket *so, int refcount, void *lr_saved)
1454*2c2f96dcSApple OSS Distributions {
1455*2c2f96dcSApple OSS Distributions 	lck_mtx_t *mutex_held = so->so_proto->pr_domain->dom_mtx;
1456*2c2f96dcSApple OSS Distributions #ifdef MORE_LOCKING_DEBUG
1457*2c2f96dcSApple OSS Distributions 	LCK_MTX_ASSERT(mutex_held, LCK_MTX_ASSERT_OWNED);
1458*2c2f96dcSApple OSS Distributions #endif
1459*2c2f96dcSApple OSS Distributions 	so->unlock_lr[so->next_unlock_lr] = lr_saved;
1460*2c2f96dcSApple OSS Distributions 	so->next_unlock_lr = (so->next_unlock_lr + 1) % SO_LCKDBG_MAX;
1461*2c2f96dcSApple OSS Distributions 
1462*2c2f96dcSApple OSS Distributions 	if (refcount) {
1463*2c2f96dcSApple OSS Distributions 		if (so->so_usecount <= 0) {
1464*2c2f96dcSApple OSS Distributions 			panic("%s: bad refcount=%d so=%p (%d, %d, %d) "
1465*2c2f96dcSApple OSS Distributions 			    "lrh=%s", __func__, so->so_usecount, so,
1466*2c2f96dcSApple OSS Distributions 			    SOCK_DOM(so), so->so_type,
1467*2c2f96dcSApple OSS Distributions 			    SOCK_PROTO(so), solockhistory_nr(so));
1468*2c2f96dcSApple OSS Distributions 			/* NOTREACHED */
1469*2c2f96dcSApple OSS Distributions 		}
1470*2c2f96dcSApple OSS Distributions 
1471*2c2f96dcSApple OSS Distributions 		so->so_usecount--;
1472*2c2f96dcSApple OSS Distributions 		if (so->so_usecount == 0) {
1473*2c2f96dcSApple OSS Distributions 			vsock_sofreelastref(so, 1);
1474*2c2f96dcSApple OSS Distributions 		}
1475*2c2f96dcSApple OSS Distributions 	}
1476*2c2f96dcSApple OSS Distributions 	lck_mtx_unlock(mutex_held);
1477*2c2f96dcSApple OSS Distributions 
1478*2c2f96dcSApple OSS Distributions 	return 0;
1479*2c2f96dcSApple OSS Distributions }
1480*2c2f96dcSApple OSS Distributions 
1481*2c2f96dcSApple OSS Distributions static struct protosw vsocksw[] = {
1482*2c2f96dcSApple OSS Distributions 	{
1483*2c2f96dcSApple OSS Distributions 		.pr_type =              SOCK_STREAM,
1484*2c2f96dcSApple OSS Distributions 		.pr_protocol =          0,
1485*2c2f96dcSApple OSS Distributions 		.pr_flags =             PR_CONNREQUIRED | PR_WANTRCVD,
1486*2c2f96dcSApple OSS Distributions 		.pr_init =              vsock_init,
1487*2c2f96dcSApple OSS Distributions 		.pr_unlock =            vsock_unlock,
1488*2c2f96dcSApple OSS Distributions 		.pr_usrreqs =           &vsock_usrreqs,
1489*2c2f96dcSApple OSS Distributions 	}
1490*2c2f96dcSApple OSS Distributions };
1491*2c2f96dcSApple OSS Distributions 
1492*2c2f96dcSApple OSS Distributions static const int vsock_proto_count = (sizeof(vsocksw) / sizeof(struct protosw));
1493*2c2f96dcSApple OSS Distributions 
1494*2c2f96dcSApple OSS Distributions /* VSock Domain */
1495*2c2f96dcSApple OSS Distributions 
1496*2c2f96dcSApple OSS Distributions static struct domain *vsock_domain = NULL;
1497*2c2f96dcSApple OSS Distributions 
1498*2c2f96dcSApple OSS Distributions static void
vsock_dinit(struct domain * dp)1499*2c2f96dcSApple OSS Distributions vsock_dinit(struct domain *dp)
1500*2c2f96dcSApple OSS Distributions {
1501*2c2f96dcSApple OSS Distributions 	// The VSock domain is initialized with a singleton pattern.
1502*2c2f96dcSApple OSS Distributions 	VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
1503*2c2f96dcSApple OSS Distributions 	VERIFY(vsock_domain == NULL);
1504*2c2f96dcSApple OSS Distributions 	vsock_domain = dp;
1505*2c2f96dcSApple OSS Distributions 
1506*2c2f96dcSApple OSS Distributions 	// Add protocols and initialize.
1507*2c2f96dcSApple OSS Distributions 	for (int i = 0; i < vsock_proto_count; i++) {
1508*2c2f96dcSApple OSS Distributions 		net_add_proto((struct protosw *)&vsocksw[i], dp, 1);
1509*2c2f96dcSApple OSS Distributions 	}
1510*2c2f96dcSApple OSS Distributions }
1511*2c2f96dcSApple OSS Distributions 
1512*2c2f96dcSApple OSS Distributions struct domain vsockdomain_s = {
1513*2c2f96dcSApple OSS Distributions 	.dom_family =           PF_VSOCK,
1514*2c2f96dcSApple OSS Distributions 	.dom_name =             "vsock",
1515*2c2f96dcSApple OSS Distributions 	.dom_init =             vsock_dinit,
1516*2c2f96dcSApple OSS Distributions 	.dom_maxrtkey =         sizeof(struct sockaddr_vm),
1517*2c2f96dcSApple OSS Distributions 	.dom_protohdrlen =      sizeof(struct sockaddr_vm),
1518*2c2f96dcSApple OSS Distributions };
1519