xref: /xnu-8020.140.41/bsd/kern/kpi_socket.c (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1 /*
2  * Copyright (c) 2003-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #define __KPI__
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/socketvar.h>
35 #include <sys/param.h>
36 #include <sys/proc.h>
37 #include <sys/errno.h>
38 #include <sys/malloc.h>
39 #include <sys/protosw.h>
40 #include <sys/domain.h>
41 #include <sys/mbuf.h>
42 #include <sys/mcache.h>
43 #include <sys/fcntl.h>
44 #include <sys/filio.h>
45 #include <sys/uio_internal.h>
46 #include <kern/locks.h>
47 #include <net/net_api_stats.h>
48 #include <netinet/in.h>
49 #include <libkern/OSAtomic.h>
50 #include <stdbool.h>
51 
52 #if SKYWALK
53 #include <skywalk/core/skywalk_var.h>
54 #endif /* SKYWALK */
55 
56 static errno_t sock_send_internal(socket_t, const struct msghdr *,
57     mbuf_t, int, size_t *);
58 
59 #undef sock_accept
60 #undef sock_socket
61 errno_t sock_accept(socket_t so, struct sockaddr *from, int fromlen,
62     int flags, sock_upcall callback, void *cookie, socket_t *new_so);
63 errno_t sock_socket(int domain, int type, int protocol, sock_upcall callback,
64     void *context, socket_t *new_so);
65 
66 static errno_t sock_accept_common(socket_t sock, struct sockaddr *from,
67     int fromlen, int flags, sock_upcall callback, void *cookie,
68     socket_t *new_sock, bool is_internal);
69 static errno_t sock_socket_common(int domain, int type, int protocol,
70     sock_upcall callback, void *context, socket_t *new_so, bool is_internal);
71 
72 errno_t
sock_accept_common(socket_t sock,struct sockaddr * from,int fromlen,int flags,sock_upcall callback,void * cookie,socket_t * new_sock,bool is_internal)73 sock_accept_common(socket_t sock, struct sockaddr *from, int fromlen, int flags,
74     sock_upcall callback, void *cookie, socket_t *new_sock, bool is_internal)
75 {
76 	struct sockaddr *sa;
77 	struct socket *new_so;
78 	lck_mtx_t *mutex_held;
79 	int dosocklock;
80 	errno_t error = 0;
81 
82 	if (sock == NULL || new_sock == NULL) {
83 		return EINVAL;
84 	}
85 
86 	socket_lock(sock, 1);
87 	if ((sock->so_options & SO_ACCEPTCONN) == 0) {
88 		socket_unlock(sock, 1);
89 		return EINVAL;
90 	}
91 	if ((flags & ~(MSG_DONTWAIT)) != 0) {
92 		socket_unlock(sock, 1);
93 		return ENOTSUP;
94 	}
95 check_again:
96 	if (((flags & MSG_DONTWAIT) != 0 || (sock->so_state & SS_NBIO) != 0) &&
97 	    sock->so_comp.tqh_first == NULL) {
98 		socket_unlock(sock, 1);
99 		return EWOULDBLOCK;
100 	}
101 
102 	if (sock->so_proto->pr_getlock != NULL) {
103 		mutex_held = (*sock->so_proto->pr_getlock)(sock, PR_F_WILLUNLOCK);
104 		dosocklock = 1;
105 	} else {
106 		mutex_held = sock->so_proto->pr_domain->dom_mtx;
107 		dosocklock = 0;
108 	}
109 
110 	while (TAILQ_EMPTY(&sock->so_comp) && sock->so_error == 0) {
111 		if (sock->so_state & SS_CANTRCVMORE) {
112 			sock->so_error = ECONNABORTED;
113 			break;
114 		}
115 		error = msleep((caddr_t)&sock->so_timeo, mutex_held,
116 		    PSOCK | PCATCH, "sock_accept", NULL);
117 		if (error != 0) {
118 			socket_unlock(sock, 1);
119 			return error;
120 		}
121 	}
122 	if (sock->so_error != 0) {
123 		error = sock->so_error;
124 		sock->so_error = 0;
125 		socket_unlock(sock, 1);
126 		return error;
127 	}
128 
129 	so_acquire_accept_list(sock, NULL);
130 	if (TAILQ_EMPTY(&sock->so_comp)) {
131 		so_release_accept_list(sock);
132 		goto check_again;
133 	}
134 	new_so = TAILQ_FIRST(&sock->so_comp);
135 	TAILQ_REMOVE(&sock->so_comp, new_so, so_list);
136 	new_so->so_state &= ~SS_COMP;
137 	new_so->so_head = NULL;
138 	sock->so_qlen--;
139 
140 	so_release_accept_list(sock);
141 
142 	/*
143 	 * Count the accepted socket as an in-kernel socket
144 	 */
145 	new_so->so_flags1 |= SOF1_IN_KERNEL_SOCKET;
146 	INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_in_kernel_total);
147 	if (is_internal) {
148 		INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_in_kernel_os_total);
149 	}
150 
151 	/*
152 	 * Pass the pre-accepted socket to any interested socket filter(s).
153 	 * Upon failure, the socket would have been closed by the callee.
154 	 */
155 	if (new_so->so_filt != NULL) {
156 		/*
157 		 * Temporarily drop the listening socket's lock before we
158 		 * hand off control over to the socket filter(s), but keep
159 		 * a reference so that it won't go away.  We'll grab it
160 		 * again once we're done with the filter(s).
161 		 */
162 		socket_unlock(sock, 0);
163 		if ((error = soacceptfilter(new_so, sock)) != 0) {
164 			/* Drop reference on listening socket */
165 			sodereference(sock);
166 			return error;
167 		}
168 		socket_lock(sock, 0);
169 	}
170 
171 	if (dosocklock) {
172 		LCK_MTX_ASSERT(new_so->so_proto->pr_getlock(new_so, 0),
173 		    LCK_MTX_ASSERT_NOTOWNED);
174 		socket_lock(new_so, 1);
175 	}
176 
177 	(void) soacceptlock(new_so, &sa, 0);
178 
179 	socket_unlock(sock, 1); /* release the head */
180 
181 	/* see comments in sock_setupcall() */
182 	if (callback != NULL) {
183 #if (defined(__arm__) || defined(__arm64__))
184 		sock_setupcalls_locked(new_so, callback, cookie, callback, cookie, 0);
185 #else /* (defined(__arm__) || defined(__arm64__)) */
186 		sock_setupcalls_locked(new_so, callback, cookie, NULL, NULL, 0);
187 #endif /* (defined(__arm__) || defined(__arm64__)) */
188 	}
189 
190 	if (sa != NULL && from != NULL) {
191 		if (fromlen > sa->sa_len) {
192 			fromlen = sa->sa_len;
193 		}
194 		memcpy(from, sa, fromlen);
195 	}
196 	free_sockaddr(sa);
197 
198 	/*
199 	 * If the socket has been marked as inactive by sosetdefunct(),
200 	 * disallow further operations on it.
201 	 */
202 	if (new_so->so_flags & SOF_DEFUNCT) {
203 		(void) sodefunct(current_proc(), new_so,
204 		    SHUTDOWN_SOCKET_LEVEL_DISCONNECT_INTERNAL);
205 	}
206 	*new_sock = new_so;
207 	if (dosocklock) {
208 		socket_unlock(new_so, 1);
209 	}
210 	return error;
211 }
212 
213 errno_t
sock_accept(socket_t sock,struct sockaddr * from,int fromlen,int flags,sock_upcall callback,void * cookie,socket_t * new_sock)214 sock_accept(socket_t sock, struct sockaddr *from, int fromlen, int flags,
215     sock_upcall callback, void *cookie, socket_t *new_sock)
216 {
217 	return sock_accept_common(sock, from, fromlen, flags,
218 	           callback, cookie, new_sock, false);
219 }
220 
221 errno_t
sock_accept_internal(socket_t sock,struct sockaddr * from,int fromlen,int flags,sock_upcall callback,void * cookie,socket_t * new_sock)222 sock_accept_internal(socket_t sock, struct sockaddr *from, int fromlen, int flags,
223     sock_upcall callback, void *cookie, socket_t *new_sock)
224 {
225 	return sock_accept_common(sock, from, fromlen, flags,
226 	           callback, cookie, new_sock, true);
227 }
228 
229 errno_t
sock_bind(socket_t sock,const struct sockaddr * to)230 sock_bind(socket_t sock, const struct sockaddr *to)
231 {
232 	int error = 0;
233 	struct sockaddr *sa = NULL;
234 	struct sockaddr_storage ss;
235 
236 	if (sock == NULL || to == NULL) {
237 		return EINVAL;
238 	}
239 
240 	if (to->sa_len > sizeof(ss)) {
241 		sa = kalloc_data(to->sa_len, Z_WAITOK | Z_ZERO | Z_NOFAIL);
242 	} else {
243 		sa = (struct sockaddr *)&ss;
244 	}
245 	memcpy(sa, to, to->sa_len);
246 
247 	error = sobindlock(sock, sa, 1);        /* will lock socket */
248 
249 	if (sa != (struct sockaddr *)&ss) {
250 		kfree_data(sa, sa->sa_len);
251 	}
252 
253 	return error;
254 }
255 
256 errno_t
sock_connect(socket_t sock,const struct sockaddr * to,int flags)257 sock_connect(socket_t sock, const struct sockaddr *to, int flags)
258 {
259 	int error = 0;
260 	lck_mtx_t *mutex_held;
261 	struct sockaddr *sa = NULL;
262 	struct sockaddr_storage ss;
263 
264 	if (sock == NULL || to == NULL) {
265 		return EINVAL;
266 	}
267 
268 	if (to->sa_len > sizeof(ss)) {
269 		sa = kalloc_data(to->sa_len,
270 		    (flags & MSG_DONTWAIT) ? Z_NOWAIT : Z_WAITOK);
271 		if (sa == NULL) {
272 			return ENOBUFS;
273 		}
274 	} else {
275 		sa = (struct sockaddr *)&ss;
276 	}
277 	memcpy(sa, to, to->sa_len);
278 
279 	socket_lock(sock, 1);
280 
281 	if ((sock->so_state & SS_ISCONNECTING) &&
282 	    ((sock->so_state & SS_NBIO) != 0 || (flags & MSG_DONTWAIT) != 0)) {
283 		error = EALREADY;
284 		goto out;
285 	}
286 
287 #if SKYWALK
288 	sk_protect_t protect = sk_async_transmit_protect();
289 #endif /* SKYWALK */
290 
291 	error = soconnectlock(sock, sa, 0);
292 
293 #if SKYWALK
294 	sk_async_transmit_unprotect(protect);
295 #endif /* SKYWALK */
296 
297 	if (!error) {
298 		if ((sock->so_state & SS_ISCONNECTING) &&
299 		    ((sock->so_state & SS_NBIO) != 0 ||
300 		    (flags & MSG_DONTWAIT) != 0)) {
301 			error = EINPROGRESS;
302 			goto out;
303 		}
304 
305 		if (sock->so_proto->pr_getlock != NULL) {
306 			mutex_held = (*sock->so_proto->pr_getlock)(sock, PR_F_WILLUNLOCK);
307 		} else {
308 			mutex_held = sock->so_proto->pr_domain->dom_mtx;
309 		}
310 
311 		while ((sock->so_state & SS_ISCONNECTING) &&
312 		    sock->so_error == 0) {
313 			error = msleep((caddr_t)&sock->so_timeo,
314 			    mutex_held, PSOCK | PCATCH, "sock_connect", NULL);
315 			if (error != 0) {
316 				break;
317 			}
318 		}
319 
320 		if (error == 0) {
321 			error = sock->so_error;
322 			sock->so_error = 0;
323 		}
324 	} else {
325 		sock->so_state &= ~SS_ISCONNECTING;
326 	}
327 out:
328 	socket_unlock(sock, 1);
329 
330 	if (sa != (struct sockaddr *)&ss) {
331 		kfree_data(sa, sa->sa_len);
332 	}
333 
334 	return error;
335 }
336 
337 errno_t
sock_connectwait(socket_t sock,const struct timeval * tv)338 sock_connectwait(socket_t sock, const struct timeval *tv)
339 {
340 	lck_mtx_t *mutex_held;
341 	errno_t retval = 0;
342 	struct timespec ts;
343 
344 	socket_lock(sock, 1);
345 
346 	/* Check if we're already connected or if we've already errored out */
347 	if ((sock->so_state & SS_ISCONNECTING) == 0 || sock->so_error != 0) {
348 		if (sock->so_error != 0) {
349 			retval = sock->so_error;
350 			sock->so_error = 0;
351 		} else {
352 			if ((sock->so_state & SS_ISCONNECTED) != 0) {
353 				retval = 0;
354 			} else {
355 				retval = EINVAL;
356 			}
357 		}
358 		goto done;
359 	}
360 
361 	/* copied translation from timeval to hertz from SO_RCVTIMEO handling */
362 	if (tv->tv_sec < 0 || tv->tv_sec > SHRT_MAX / hz ||
363 	    tv->tv_usec < 0 || tv->tv_usec >= 1000000) {
364 		retval = EDOM;
365 		goto done;
366 	}
367 
368 	ts.tv_sec = tv->tv_sec;
369 	ts.tv_nsec = (tv->tv_usec * (integer_t)NSEC_PER_USEC);
370 	if ((ts.tv_sec + (ts.tv_nsec / (long)NSEC_PER_SEC)) / 100 > SHRT_MAX) {
371 		retval = EDOM;
372 		goto done;
373 	}
374 
375 	if (sock->so_proto->pr_getlock != NULL) {
376 		mutex_held = (*sock->so_proto->pr_getlock)(sock, PR_F_WILLUNLOCK);
377 	} else {
378 		mutex_held = sock->so_proto->pr_domain->dom_mtx;
379 	}
380 
381 	msleep((caddr_t)&sock->so_timeo, mutex_held,
382 	    PSOCK, "sock_connectwait", &ts);
383 
384 	/* Check if we're still waiting to connect */
385 	if ((sock->so_state & SS_ISCONNECTING) && sock->so_error == 0) {
386 		retval = EINPROGRESS;
387 		goto done;
388 	}
389 
390 	if (sock->so_error != 0) {
391 		retval = sock->so_error;
392 		sock->so_error = 0;
393 	}
394 
395 done:
396 	socket_unlock(sock, 1);
397 	return retval;
398 }
399 
400 errno_t
sock_nointerrupt(socket_t sock,int on)401 sock_nointerrupt(socket_t sock, int on)
402 {
403 	socket_lock(sock, 1);
404 
405 	if (on) {
406 		sock->so_rcv.sb_flags |= SB_NOINTR;     /* This isn't safe */
407 		sock->so_snd.sb_flags |= SB_NOINTR;     /* This isn't safe */
408 	} else {
409 		sock->so_rcv.sb_flags &= ~SB_NOINTR;    /* This isn't safe */
410 		sock->so_snd.sb_flags &= ~SB_NOINTR;    /* This isn't safe */
411 	}
412 
413 	socket_unlock(sock, 1);
414 
415 	return 0;
416 }
417 
418 errno_t
sock_getpeername(socket_t sock,struct sockaddr * peername,int peernamelen)419 sock_getpeername(socket_t sock, struct sockaddr *peername, int peernamelen)
420 {
421 	int error;
422 	struct sockaddr *sa = NULL;
423 
424 	if (sock == NULL || peername == NULL || peernamelen < 0) {
425 		return EINVAL;
426 	}
427 
428 	socket_lock(sock, 1);
429 	if (!(sock->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING))) {
430 		socket_unlock(sock, 1);
431 		return ENOTCONN;
432 	}
433 	error = sogetaddr_locked(sock, &sa, 1);
434 	socket_unlock(sock, 1);
435 	if (error == 0) {
436 		if (peernamelen > sa->sa_len) {
437 			peernamelen = sa->sa_len;
438 		}
439 		memcpy(peername, sa, peernamelen);
440 		free_sockaddr(sa);
441 	}
442 	return error;
443 }
444 
445 errno_t
sock_getsockname(socket_t sock,struct sockaddr * sockname,int socknamelen)446 sock_getsockname(socket_t sock, struct sockaddr *sockname, int socknamelen)
447 {
448 	int error;
449 	struct sockaddr *sa = NULL;
450 
451 	if (sock == NULL || sockname == NULL || socknamelen < 0) {
452 		return EINVAL;
453 	}
454 
455 	socket_lock(sock, 1);
456 	error = sogetaddr_locked(sock, &sa, 0);
457 	socket_unlock(sock, 1);
458 	if (error == 0) {
459 		if (socknamelen > sa->sa_len) {
460 			socknamelen = sa->sa_len;
461 		}
462 		memcpy(sockname, sa, socknamelen);
463 		free_sockaddr(sa);
464 	}
465 	return error;
466 }
467 
468 __private_extern__ int
sogetaddr_locked(struct socket * so,struct sockaddr ** psa,int peer)469 sogetaddr_locked(struct socket *so, struct sockaddr **psa, int peer)
470 {
471 	int error;
472 
473 	if (so == NULL || psa == NULL) {
474 		return EINVAL;
475 	}
476 
477 	*psa = NULL;
478 	error = peer ? so->so_proto->pr_usrreqs->pru_peeraddr(so, psa) :
479 	    so->so_proto->pr_usrreqs->pru_sockaddr(so, psa);
480 
481 	if (error == 0 && *psa == NULL) {
482 		error = ENOMEM;
483 	} else if (error != 0) {
484 		free_sockaddr(*psa);
485 	}
486 	return error;
487 }
488 
489 errno_t
sock_getaddr(socket_t sock,struct sockaddr ** psa,int peer)490 sock_getaddr(socket_t sock, struct sockaddr **psa, int peer)
491 {
492 	int error;
493 
494 	if (sock == NULL || psa == NULL) {
495 		return EINVAL;
496 	}
497 
498 	socket_lock(sock, 1);
499 	error = sogetaddr_locked(sock, psa, peer);
500 	socket_unlock(sock, 1);
501 
502 	return error;
503 }
504 
505 void
sock_freeaddr(struct sockaddr * sa)506 sock_freeaddr(struct sockaddr *sa)
507 {
508 	free_sockaddr(sa);
509 }
510 
511 errno_t
sock_getsockopt(socket_t sock,int level,int optname,void * optval,int * optlen)512 sock_getsockopt(socket_t sock, int level, int optname, void *optval,
513     int *optlen)
514 {
515 	int error = 0;
516 	struct sockopt  sopt;
517 
518 	if (sock == NULL || optval == NULL || optlen == NULL) {
519 		return EINVAL;
520 	}
521 
522 	sopt.sopt_dir = SOPT_GET;
523 	sopt.sopt_level = level;
524 	sopt.sopt_name = optname;
525 	sopt.sopt_val = CAST_USER_ADDR_T(optval);
526 	sopt.sopt_valsize = *optlen;
527 	sopt.sopt_p = kernproc;
528 	error = sogetoptlock(sock, &sopt, 1);   /* will lock socket */
529 	if (error == 0) {
530 		*optlen = (uint32_t)sopt.sopt_valsize;
531 	}
532 	return error;
533 }
534 
535 errno_t
sock_ioctl(socket_t sock,unsigned long request,void * argp)536 sock_ioctl(socket_t sock, unsigned long request, void *argp)
537 {
538 	return soioctl(sock, request, argp, kernproc); /* will lock socket */
539 }
540 
541 errno_t
sock_setsockopt(socket_t sock,int level,int optname,const void * optval,int optlen)542 sock_setsockopt(socket_t sock, int level, int optname, const void *optval,
543     int optlen)
544 {
545 	struct sockopt  sopt;
546 
547 	if (sock == NULL || optval == NULL) {
548 		return EINVAL;
549 	}
550 
551 	sopt.sopt_dir = SOPT_SET;
552 	sopt.sopt_level = level;
553 	sopt.sopt_name = optname;
554 	sopt.sopt_val = CAST_USER_ADDR_T(optval);
555 	sopt.sopt_valsize = optlen;
556 	sopt.sopt_p = kernproc;
557 	return sosetoptlock(sock, &sopt, 1); /* will lock socket */
558 }
559 
560 /*
561  * This follows the recommended mappings between DSCP code points
562  * and WMM access classes.
563  */
564 static uint32_t
so_tc_from_dscp(uint8_t dscp)565 so_tc_from_dscp(uint8_t dscp)
566 {
567 	uint32_t tc;
568 
569 	if (dscp >= 0x30 && dscp <= 0x3f) {
570 		tc = SO_TC_VO;
571 	} else if (dscp >= 0x20 && dscp <= 0x2f) {
572 		tc = SO_TC_VI;
573 	} else if (dscp >= 0x08 && dscp <= 0x17) {
574 		tc = SO_TC_BK_SYS;
575 	} else {
576 		tc = SO_TC_BE;
577 	}
578 
579 	return tc;
580 }
581 
582 errno_t
sock_settclassopt(socket_t sock,const void * optval,size_t optlen)583 sock_settclassopt(socket_t sock, const void *optval, size_t optlen)
584 {
585 	errno_t error = 0;
586 	struct sockopt sopt;
587 	int sotc;
588 
589 	if (sock == NULL || optval == NULL || optlen != sizeof(int)) {
590 		return EINVAL;
591 	}
592 
593 	socket_lock(sock, 1);
594 	if (!(sock->so_state & SS_ISCONNECTED)) {
595 		/*
596 		 * If the socket is not connected then we don't know
597 		 * if the destination is on LAN  or not. Skip
598 		 * setting traffic class in this case
599 		 */
600 		error = ENOTCONN;
601 		goto out;
602 	}
603 
604 	if (sock->so_proto == NULL || sock->so_proto->pr_domain == NULL ||
605 	    sock->so_pcb == NULL) {
606 		error = EINVAL;
607 		goto out;
608 	}
609 
610 	/*
611 	 * Set the socket traffic class based on the passed DSCP code point
612 	 * regardless of the scope of the destination
613 	 */
614 	sotc = so_tc_from_dscp((uint8_t)((*(const int *)optval) >> 2));
615 
616 	sopt.sopt_dir = SOPT_SET;
617 	sopt.sopt_val = CAST_USER_ADDR_T(&sotc);
618 	sopt.sopt_valsize = sizeof(sotc);
619 	sopt.sopt_p = kernproc;
620 	sopt.sopt_level = SOL_SOCKET;
621 	sopt.sopt_name = SO_TRAFFIC_CLASS;
622 
623 	error = sosetoptlock(sock, &sopt, 0);   /* already locked */
624 
625 	if (error != 0) {
626 		printf("%s: sosetopt SO_TRAFFIC_CLASS failed %d\n",
627 		    __func__, error);
628 		goto out;
629 	}
630 
631 	/*
632 	 * Check if the destination address is LAN or link local address.
633 	 * We do not want to set traffic class bits if the destination
634 	 * is not local.
635 	 */
636 	if (!so_isdstlocal(sock)) {
637 		goto out;
638 	}
639 
640 	sopt.sopt_dir = SOPT_SET;
641 	sopt.sopt_val = CAST_USER_ADDR_T(optval);
642 	sopt.sopt_valsize = optlen;
643 	sopt.sopt_p = kernproc;
644 
645 	switch (SOCK_DOM(sock)) {
646 	case PF_INET:
647 		sopt.sopt_level = IPPROTO_IP;
648 		sopt.sopt_name = IP_TOS;
649 		break;
650 	case PF_INET6:
651 		sopt.sopt_level = IPPROTO_IPV6;
652 		sopt.sopt_name = IPV6_TCLASS;
653 		break;
654 	default:
655 		error = EINVAL;
656 		goto out;
657 	}
658 
659 	error = sosetoptlock(sock, &sopt, 0);   /* already locked */
660 	socket_unlock(sock, 1);
661 	return error;
662 out:
663 	socket_unlock(sock, 1);
664 	return error;
665 }
666 
667 errno_t
sock_gettclassopt(socket_t sock,void * optval,size_t * optlen)668 sock_gettclassopt(socket_t sock, void *optval, size_t *optlen)
669 {
670 	errno_t error = 0;
671 	struct sockopt sopt;
672 
673 	if (sock == NULL || optval == NULL || optlen == NULL) {
674 		return EINVAL;
675 	}
676 
677 	sopt.sopt_dir = SOPT_GET;
678 	sopt.sopt_val = CAST_USER_ADDR_T(optval);
679 	sopt.sopt_valsize = *optlen;
680 	sopt.sopt_p = kernproc;
681 
682 	socket_lock(sock, 1);
683 	if (sock->so_proto == NULL || sock->so_proto->pr_domain == NULL) {
684 		socket_unlock(sock, 1);
685 		return EINVAL;
686 	}
687 
688 	switch (SOCK_DOM(sock)) {
689 	case PF_INET:
690 		sopt.sopt_level = IPPROTO_IP;
691 		sopt.sopt_name = IP_TOS;
692 		break;
693 	case PF_INET6:
694 		sopt.sopt_level = IPPROTO_IPV6;
695 		sopt.sopt_name = IPV6_TCLASS;
696 		break;
697 	default:
698 		socket_unlock(sock, 1);
699 		return EINVAL;
700 	}
701 	error = sogetoptlock(sock, &sopt, 0);   /* already locked */
702 	socket_unlock(sock, 1);
703 	if (error == 0) {
704 		*optlen = sopt.sopt_valsize;
705 	}
706 	return error;
707 }
708 
709 errno_t
sock_listen(socket_t sock,int backlog)710 sock_listen(socket_t sock, int backlog)
711 {
712 	if (sock == NULL) {
713 		return EINVAL;
714 	}
715 
716 	return solisten(sock, backlog); /* will lock socket */
717 }
718 
719 errno_t
sock_receive_internal(socket_t sock,struct msghdr * msg,mbuf_t * data,int flags,size_t * recvdlen)720 sock_receive_internal(socket_t sock, struct msghdr *msg, mbuf_t *data,
721     int flags, size_t *recvdlen)
722 {
723 	uio_t auio;
724 	struct mbuf *control = NULL;
725 	int error = 0;
726 	user_ssize_t length = 0;
727 	struct sockaddr *fromsa = NULL;
728 	uio_stackbuf_t uio_buf[UIO_SIZEOF((msg != NULL) ? msg->msg_iovlen : 0)];
729 
730 	if (sock == NULL) {
731 		return EINVAL;
732 	}
733 
734 	auio = uio_createwithbuffer(((msg != NULL) ? msg->msg_iovlen : 0),
735 	    0, UIO_SYSSPACE, UIO_READ, &uio_buf[0], sizeof(uio_buf));
736 	if (msg != NULL && data == NULL) {
737 		int i;
738 		struct iovec *tempp = msg->msg_iov;
739 
740 		for (i = 0; i < msg->msg_iovlen; i++) {
741 			uio_addiov(auio,
742 			    CAST_USER_ADDR_T((tempp + i)->iov_base),
743 			    (tempp + i)->iov_len);
744 		}
745 		if (uio_resid(auio) < 0) {
746 			return EINVAL;
747 		}
748 	} else if (recvdlen != NULL) {
749 		uio_setresid(auio, (uio_resid(auio) + *recvdlen));
750 	}
751 	length = uio_resid(auio);
752 
753 	if (recvdlen != NULL) {
754 		*recvdlen = 0;
755 	}
756 
757 	/* let pru_soreceive handle the socket locking */
758 	error = sock->so_proto->pr_usrreqs->pru_soreceive(sock, &fromsa, auio,
759 	    data, (msg && msg->msg_control) ? &control : NULL, &flags);
760 	if (error != 0) {
761 		goto cleanup;
762 	}
763 
764 	if (recvdlen != NULL) {
765 		*recvdlen = length - uio_resid(auio);
766 	}
767 	if (msg != NULL) {
768 		msg->msg_flags = flags;
769 
770 		if (msg->msg_name != NULL) {
771 			int salen;
772 			salen = msg->msg_namelen;
773 			if (msg->msg_namelen > 0 && fromsa != NULL) {
774 				salen = MIN(salen, fromsa->sa_len);
775 				memcpy(msg->msg_name, fromsa,
776 				    msg->msg_namelen > fromsa->sa_len ?
777 				    fromsa->sa_len : msg->msg_namelen);
778 			}
779 		}
780 
781 		if (msg->msg_control != NULL) {
782 			struct mbuf *m = control;
783 			u_char *ctlbuf = msg->msg_control;
784 			int clen = msg->msg_controllen;
785 
786 			msg->msg_controllen = 0;
787 
788 			while (m != NULL && clen > 0) {
789 				unsigned int tocopy;
790 
791 				if (clen >= m->m_len) {
792 					tocopy = m->m_len;
793 				} else {
794 					msg->msg_flags |= MSG_CTRUNC;
795 					tocopy = clen;
796 				}
797 				memcpy(ctlbuf, mtod(m, caddr_t), tocopy);
798 				ctlbuf += tocopy;
799 				clen -= tocopy;
800 				m = m->m_next;
801 			}
802 			msg->msg_controllen =
803 			    (socklen_t)((uintptr_t)ctlbuf - (uintptr_t)msg->msg_control);
804 		}
805 	}
806 
807 cleanup:
808 	if (control != NULL) {
809 		m_freem(control);
810 	}
811 	free_sockaddr(fromsa);
812 	return error;
813 }
814 
815 errno_t
sock_receive(socket_t sock,struct msghdr * msg,int flags,size_t * recvdlen)816 sock_receive(socket_t sock, struct msghdr *msg, int flags, size_t *recvdlen)
817 {
818 	if ((msg == NULL) || (msg->msg_iovlen < 1) ||
819 	    (msg->msg_iov[0].iov_len == 0) ||
820 	    (msg->msg_iov[0].iov_base == NULL)) {
821 		return EINVAL;
822 	}
823 
824 	return sock_receive_internal(sock, msg, NULL, flags, recvdlen);
825 }
826 
827 errno_t
sock_receivembuf(socket_t sock,struct msghdr * msg,mbuf_t * data,int flags,size_t * recvlen)828 sock_receivembuf(socket_t sock, struct msghdr *msg, mbuf_t *data, int flags,
829     size_t *recvlen)
830 {
831 	if (data == NULL || recvlen == 0 || *recvlen <= 0 || (msg != NULL &&
832 	    (msg->msg_iov != NULL || msg->msg_iovlen != 0))) {
833 		return EINVAL;
834 	}
835 
836 	return sock_receive_internal(sock, msg, data, flags, recvlen);
837 }
838 
839 errno_t
sock_send_internal(socket_t sock,const struct msghdr * msg,mbuf_t data,int flags,size_t * sentlen)840 sock_send_internal(socket_t sock, const struct msghdr *msg, mbuf_t data,
841     int flags, size_t *sentlen)
842 {
843 	uio_t auio = NULL;
844 	struct mbuf *control = NULL;
845 	int error = 0;
846 	user_ssize_t datalen = 0;
847 	char *uio_bufp = NULL;
848 
849 	if (sock == NULL) {
850 		error = EINVAL;
851 		goto errorout;
852 	}
853 
854 	if (data == NULL && msg != NULL) {
855 		struct iovec *tempp = msg->msg_iov;
856 
857 		uio_bufp = kalloc_data(UIO_SIZEOF(msg->msg_iovlen), Z_WAITOK);
858 		if (uio_bufp == NULL) {
859 #if (DEBUG || DEVELOPMENT)
860 			printf("sock_send_internal: so %p kalloc_data(%lu) failed, ENOMEM\n",
861 			    sock, UIO_SIZEOF(msg->msg_iovlen));
862 #endif /* (DEBUG || DEVELOPMENT) */
863 			error = ENOMEM;
864 			goto errorout;
865 		}
866 		auio = uio_createwithbuffer(msg->msg_iovlen, 0,
867 		    UIO_SYSSPACE, UIO_WRITE, uio_bufp, UIO_SIZEOF(msg->msg_iovlen));
868 		if (auio == NULL) {
869 #if (DEBUG || DEVELOPMENT)
870 			printf("sock_send_internal: so %p uio_createwithbuffer(%lu) failed, ENOMEM\n",
871 			    sock, UIO_SIZEOF(msg->msg_iovlen));
872 #endif /* (DEBUG || DEVELOPMENT) */
873 			error = ENOMEM;
874 			goto errorout;
875 		}
876 		if (tempp != NULL) {
877 			int i;
878 
879 			for (i = 0; i < msg->msg_iovlen; i++) {
880 				uio_addiov(auio,
881 				    CAST_USER_ADDR_T((tempp + i)->iov_base),
882 				    (tempp + i)->iov_len);
883 			}
884 
885 			if (uio_resid(auio) < 0) {
886 				error = EINVAL;
887 				goto errorout;
888 			}
889 		}
890 	}
891 
892 	if (sentlen != NULL) {
893 		*sentlen = 0;
894 	}
895 
896 	if (auio != NULL) {
897 		datalen = uio_resid(auio);
898 	} else {
899 		datalen = data->m_pkthdr.len;
900 	}
901 
902 	if (msg != NULL && msg->msg_control) {
903 		if ((size_t)msg->msg_controllen < sizeof(struct cmsghdr)) {
904 			error = EINVAL;
905 			goto errorout;
906 		}
907 
908 		if ((size_t)msg->msg_controllen > MLEN) {
909 			error = EINVAL;
910 			goto errorout;
911 		}
912 
913 		control = m_get(M_NOWAIT, MT_CONTROL);
914 		if (control == NULL) {
915 			error = ENOMEM;
916 			goto errorout;
917 		}
918 		memcpy(mtod(control, caddr_t), msg->msg_control,
919 		    msg->msg_controllen);
920 		control->m_len = msg->msg_controllen;
921 	}
922 
923 #if SKYWALK
924 	sk_protect_t protect = sk_async_transmit_protect();
925 #endif /* SKYWALK */
926 
927 	error = sock->so_proto->pr_usrreqs->pru_sosend(sock, msg != NULL ?
928 	    (struct sockaddr *)msg->msg_name : NULL, auio, data,
929 	    control, flags);
930 
931 #if SKYWALK
932 	sk_async_transmit_unprotect(protect);
933 #endif /* SKYWALK */
934 
935 	/*
936 	 * Residual data is possible in the case of IO vectors but not
937 	 * in the mbuf case since the latter is treated as atomic send.
938 	 * If pru_sosend() consumed a portion of the iovecs data and
939 	 * the error returned is transient, treat it as success; this
940 	 * is consistent with sendit() behavior.
941 	 */
942 	if (auio != NULL && uio_resid(auio) != datalen &&
943 	    (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) {
944 		error = 0;
945 	}
946 
947 	if (error == 0 && sentlen != NULL) {
948 		if (auio != NULL) {
949 			*sentlen = datalen - uio_resid(auio);
950 		} else {
951 			*sentlen = datalen;
952 		}
953 	}
954 	if (uio_bufp != NULL) {
955 		kfree_data(uio_bufp, UIO_SIZEOF(msg->msg_iovlen));
956 	}
957 
958 	return error;
959 
960 /*
961  * In cases where we detect an error before returning, we need to
962  * free the mbuf chain if there is one. sosend (and pru_sosend) will
963  * free the mbuf chain if they encounter an error.
964  */
965 errorout:
966 	if (control) {
967 		m_freem(control);
968 	}
969 	if (data) {
970 		m_freem(data);
971 	}
972 	if (sentlen) {
973 		*sentlen = 0;
974 	}
975 	if (uio_bufp != NULL) {
976 		kfree_data(uio_bufp, UIO_SIZEOF(msg->msg_iovlen));
977 	}
978 	return error;
979 }
980 
981 errno_t
sock_send(socket_t sock,const struct msghdr * msg,int flags,size_t * sentlen)982 sock_send(socket_t sock, const struct msghdr *msg, int flags, size_t *sentlen)
983 {
984 	if (msg == NULL || msg->msg_iov == NULL || msg->msg_iovlen < 1) {
985 		return EINVAL;
986 	}
987 
988 	return sock_send_internal(sock, msg, NULL, flags, sentlen);
989 }
990 
991 errno_t
sock_sendmbuf(socket_t sock,const struct msghdr * msg,mbuf_t data,int flags,size_t * sentlen)992 sock_sendmbuf(socket_t sock, const struct msghdr *msg, mbuf_t data,
993     int flags, size_t *sentlen)
994 {
995 	if (data == NULL || (msg != NULL && (msg->msg_iov != NULL ||
996 	    msg->msg_iovlen != 0))) {
997 		if (data != NULL) {
998 			m_freem(data);
999 		}
1000 		return EINVAL;
1001 	}
1002 	return sock_send_internal(sock, msg, data, flags, sentlen);
1003 }
1004 
1005 errno_t
sock_shutdown(socket_t sock,int how)1006 sock_shutdown(socket_t sock, int how)
1007 {
1008 	if (sock == NULL) {
1009 		return EINVAL;
1010 	}
1011 
1012 	return soshutdown(sock, how);
1013 }
1014 
1015 errno_t
sock_socket_common(int domain,int type,int protocol,sock_upcall callback,void * context,socket_t * new_so,bool is_internal)1016 sock_socket_common(int domain, int type, int protocol, sock_upcall callback,
1017     void *context, socket_t *new_so, bool is_internal)
1018 {
1019 	int error = 0;
1020 
1021 	if (new_so == NULL) {
1022 		return EINVAL;
1023 	}
1024 
1025 	/* socreate will create an initial so_count */
1026 	error = socreate(domain, new_so, type, protocol);
1027 	if (error == 0) {
1028 		/*
1029 		 * This is an in-kernel socket
1030 		 */
1031 		(*new_so)->so_flags1 |= SOF1_IN_KERNEL_SOCKET;
1032 		INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_in_kernel_total);
1033 		if (is_internal) {
1034 			INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_in_kernel_os_total);
1035 		}
1036 
1037 		/* see comments in sock_setupcall() */
1038 		if (callback != NULL) {
1039 			sock_setupcall(*new_so, callback, context);
1040 		}
1041 		/*
1042 		 * last_pid and last_upid should be zero for sockets
1043 		 * created using sock_socket
1044 		 */
1045 		(*new_so)->last_pid = 0;
1046 		(*new_so)->last_upid = 0;
1047 	}
1048 	return error;
1049 }
1050 
1051 errno_t
sock_socket_internal(int domain,int type,int protocol,sock_upcall callback,void * context,socket_t * new_so)1052 sock_socket_internal(int domain, int type, int protocol, sock_upcall callback,
1053     void *context, socket_t *new_so)
1054 {
1055 	return sock_socket_common(domain, type, protocol, callback,
1056 	           context, new_so, true);
1057 }
1058 
1059 errno_t
sock_socket(int domain,int type,int protocol,sock_upcall callback,void * context,socket_t * new_so)1060 sock_socket(int domain, int type, int protocol, sock_upcall callback,
1061     void *context, socket_t *new_so)
1062 {
1063 	return sock_socket_common(domain, type, protocol, callback,
1064 	           context, new_so, false);
1065 }
1066 
1067 void
sock_close(socket_t sock)1068 sock_close(socket_t sock)
1069 {
1070 	if (sock == NULL) {
1071 		return;
1072 	}
1073 
1074 	soclose(sock);
1075 }
1076 
1077 /* Do we want this to be APPLE_PRIVATE API?: YES (LD 12/23/04) */
1078 void
sock_retain(socket_t sock)1079 sock_retain(socket_t sock)
1080 {
1081 	if (sock == NULL) {
1082 		return;
1083 	}
1084 
1085 	socket_lock(sock, 1);
1086 	sock->so_retaincnt++;
1087 	sock->so_usecount++;    /* add extra reference for holding the socket */
1088 	socket_unlock(sock, 1);
1089 }
1090 
1091 /* Do we want this to be APPLE_PRIVATE API? */
1092 void
sock_release(socket_t sock)1093 sock_release(socket_t sock)
1094 {
1095 	if (sock == NULL) {
1096 		return;
1097 	}
1098 
1099 	socket_lock(sock, 1);
1100 	if (sock->so_upcallusecount > 0) {
1101 		soclose_wait_locked(sock);
1102 	}
1103 
1104 	sock->so_retaincnt--;
1105 	if (sock->so_retaincnt < 0) {
1106 		panic("%s: negative retain count (%d) for sock=%p",
1107 		    __func__, sock->so_retaincnt, sock);
1108 		/* NOTREACHED */
1109 	}
1110 	/*
1111 	 * Check SS_NOFDREF in case a close happened as sock_retain()
1112 	 * was grabbing the lock
1113 	 */
1114 	if ((sock->so_retaincnt == 0) && (sock->so_usecount == 2) &&
1115 	    (!(sock->so_state & SS_NOFDREF) ||
1116 	    (sock->so_flags & SOF_MP_SUBFLOW))) {
1117 		/* close socket only if the FD is not holding it */
1118 		soclose_locked(sock);
1119 	} else {
1120 		/* remove extra reference holding the socket */
1121 		VERIFY(sock->so_usecount > 1);
1122 		sock->so_usecount--;
1123 	}
1124 	socket_unlock(sock, 1);
1125 }
1126 
1127 errno_t
sock_setpriv(socket_t sock,int on)1128 sock_setpriv(socket_t sock, int on)
1129 {
1130 	if (sock == NULL) {
1131 		return EINVAL;
1132 	}
1133 
1134 	socket_lock(sock, 1);
1135 	if (on) {
1136 		sock->so_state |= SS_PRIV;
1137 	} else {
1138 		sock->so_state &= ~SS_PRIV;
1139 	}
1140 	socket_unlock(sock, 1);
1141 	return 0;
1142 }
1143 
1144 int
sock_isconnected(socket_t sock)1145 sock_isconnected(socket_t sock)
1146 {
1147 	int retval;
1148 
1149 	socket_lock(sock, 1);
1150 	retval = ((sock->so_state & SS_ISCONNECTED) ? 1 : 0);
1151 	socket_unlock(sock, 1);
1152 	return retval;
1153 }
1154 
1155 int
sock_isnonblocking(socket_t sock)1156 sock_isnonblocking(socket_t sock)
1157 {
1158 	int retval;
1159 
1160 	socket_lock(sock, 1);
1161 	retval = ((sock->so_state & SS_NBIO) ? 1 : 0);
1162 	socket_unlock(sock, 1);
1163 	return retval;
1164 }
1165 
1166 errno_t
sock_gettype(socket_t sock,int * outDomain,int * outType,int * outProtocol)1167 sock_gettype(socket_t sock, int *outDomain, int *outType, int *outProtocol)
1168 {
1169 	socket_lock(sock, 1);
1170 	if (outDomain != NULL) {
1171 		*outDomain = SOCK_DOM(sock);
1172 	}
1173 	if (outType != NULL) {
1174 		*outType = sock->so_type;
1175 	}
1176 	if (outProtocol != NULL) {
1177 		*outProtocol = SOCK_PROTO(sock);
1178 	}
1179 	socket_unlock(sock, 1);
1180 	return 0;
1181 }
1182 
1183 /*
1184  * Return the listening socket of a pre-accepted socket.  It returns the
1185  * listener (so_head) value of a given socket.  This is intended to be
1186  * called by a socket filter during a filter attach (sf_attach) callback.
1187  * The value returned by this routine is safe to be used only in the
1188  * context of that callback, because we hold the listener's lock across
1189  * the sflt_initsock() call.
1190  */
1191 socket_t
sock_getlistener(socket_t sock)1192 sock_getlistener(socket_t sock)
1193 {
1194 	return sock->so_head;
1195 }
1196 
1197 static inline void
sock_set_tcp_stream_priority(socket_t sock)1198 sock_set_tcp_stream_priority(socket_t sock)
1199 {
1200 	if ((SOCK_DOM(sock) == PF_INET || SOCK_DOM(sock) == PF_INET6) &&
1201 	    SOCK_TYPE(sock) == SOCK_STREAM) {
1202 		set_tcp_stream_priority(sock);
1203 	}
1204 }
1205 
1206 /*
1207  * Caller must have ensured socket is valid and won't be going away.
1208  */
1209 void
socket_set_traffic_mgt_flags_locked(socket_t sock,u_int8_t flags)1210 socket_set_traffic_mgt_flags_locked(socket_t sock, u_int8_t flags)
1211 {
1212 	u_int32_t soflags1 = 0;
1213 
1214 	if ((flags & TRAFFIC_MGT_SO_BACKGROUND)) {
1215 		soflags1 |= SOF1_TRAFFIC_MGT_SO_BACKGROUND;
1216 	}
1217 	if ((flags & TRAFFIC_MGT_TCP_RECVBG)) {
1218 		soflags1 |= SOF1_TRAFFIC_MGT_TCP_RECVBG;
1219 	}
1220 
1221 	(void) OSBitOrAtomic(soflags1, &sock->so_flags1);
1222 
1223 	sock_set_tcp_stream_priority(sock);
1224 }
1225 
1226 void
socket_set_traffic_mgt_flags(socket_t sock,u_int8_t flags)1227 socket_set_traffic_mgt_flags(socket_t sock, u_int8_t flags)
1228 {
1229 	socket_lock(sock, 1);
1230 	socket_set_traffic_mgt_flags_locked(sock, flags);
1231 	socket_unlock(sock, 1);
1232 }
1233 
1234 /*
1235  * Caller must have ensured socket is valid and won't be going away.
1236  */
1237 void
socket_clear_traffic_mgt_flags_locked(socket_t sock,u_int8_t flags)1238 socket_clear_traffic_mgt_flags_locked(socket_t sock, u_int8_t flags)
1239 {
1240 	u_int32_t soflags1 = 0;
1241 
1242 	if ((flags & TRAFFIC_MGT_SO_BACKGROUND)) {
1243 		soflags1 |= SOF1_TRAFFIC_MGT_SO_BACKGROUND;
1244 	}
1245 	if ((flags & TRAFFIC_MGT_TCP_RECVBG)) {
1246 		soflags1 |= SOF1_TRAFFIC_MGT_TCP_RECVBG;
1247 	}
1248 
1249 	(void) OSBitAndAtomic(~soflags1, &sock->so_flags1);
1250 
1251 	sock_set_tcp_stream_priority(sock);
1252 }
1253 
1254 void
socket_clear_traffic_mgt_flags(socket_t sock,u_int8_t flags)1255 socket_clear_traffic_mgt_flags(socket_t sock, u_int8_t flags)
1256 {
1257 	socket_lock(sock, 1);
1258 	socket_clear_traffic_mgt_flags_locked(sock, flags);
1259 	socket_unlock(sock, 1);
1260 }
1261 
1262 
1263 /*
1264  * Caller must have ensured socket is valid and won't be going away.
1265  */
1266 errno_t
socket_defunct(struct proc * p,socket_t so,int level)1267 socket_defunct(struct proc *p, socket_t so, int level)
1268 {
1269 	errno_t retval;
1270 
1271 	if (level != SHUTDOWN_SOCKET_LEVEL_DISCONNECT_SVC &&
1272 	    level != SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL) {
1273 		return EINVAL;
1274 	}
1275 
1276 	socket_lock(so, 1);
1277 	/*
1278 	 * SHUTDOWN_SOCKET_LEVEL_DISCONNECT_SVC level is meant to tear down
1279 	 * all of mDNSResponder IPC sockets, currently those of AF_UNIX; note
1280 	 * that this is an implementation artifact of mDNSResponder.  We do
1281 	 * a quick test against the socket buffers for SB_UNIX, since that
1282 	 * would have been set by unp_attach() at socket creation time.
1283 	 */
1284 	if (level == SHUTDOWN_SOCKET_LEVEL_DISCONNECT_SVC &&
1285 	    (so->so_rcv.sb_flags & so->so_snd.sb_flags & SB_UNIX) != SB_UNIX) {
1286 		socket_unlock(so, 1);
1287 		return EOPNOTSUPP;
1288 	}
1289 	retval = sosetdefunct(p, so, level, TRUE);
1290 	if (retval == 0) {
1291 		retval = sodefunct(p, so, level);
1292 	}
1293 	socket_unlock(so, 1);
1294 	return retval;
1295 }
1296 
1297 void
sock_setupcalls_locked(socket_t sock,sock_upcall rcallback,void * rcontext,sock_upcall wcallback,void * wcontext,int locked)1298 sock_setupcalls_locked(socket_t sock, sock_upcall rcallback, void *rcontext,
1299     sock_upcall wcallback, void *wcontext, int locked)
1300 {
1301 	if (rcallback != NULL) {
1302 		sock->so_rcv.sb_flags |= SB_UPCALL;
1303 		if (locked) {
1304 			sock->so_rcv.sb_flags |= SB_UPCALL_LOCK;
1305 		}
1306 		sock->so_rcv.sb_upcall = rcallback;
1307 		sock->so_rcv.sb_upcallarg = rcontext;
1308 	} else {
1309 		sock->so_rcv.sb_flags &= ~(SB_UPCALL | SB_UPCALL_LOCK);
1310 		sock->so_rcv.sb_upcall = NULL;
1311 		sock->so_rcv.sb_upcallarg = NULL;
1312 	}
1313 
1314 	if (wcallback != NULL) {
1315 		sock->so_snd.sb_flags |= SB_UPCALL;
1316 		if (locked) {
1317 			sock->so_snd.sb_flags |= SB_UPCALL_LOCK;
1318 		}
1319 		sock->so_snd.sb_upcall = wcallback;
1320 		sock->so_snd.sb_upcallarg = wcontext;
1321 	} else {
1322 		sock->so_snd.sb_flags &= ~(SB_UPCALL | SB_UPCALL_LOCK);
1323 		sock->so_snd.sb_upcall = NULL;
1324 		sock->so_snd.sb_upcallarg = NULL;
1325 	}
1326 }
1327 
1328 errno_t
sock_setupcall(socket_t sock,sock_upcall callback,void * context)1329 sock_setupcall(socket_t sock, sock_upcall callback, void *context)
1330 {
1331 	if (sock == NULL) {
1332 		return EINVAL;
1333 	}
1334 
1335 	/*
1336 	 * Note that we don't wait for any in progress upcall to complete.
1337 	 * On embedded, sock_setupcall() causes both read and write
1338 	 * callbacks to be set; on desktop, only read callback is set
1339 	 * to maintain legacy KPI behavior.
1340 	 *
1341 	 * The newer sock_setupcalls() KPI should be used instead to set
1342 	 * the read and write callbacks and their respective parameters.
1343 	 */
1344 	socket_lock(sock, 1);
1345 #if (defined(__arm__) || defined(__arm64__))
1346 	sock_setupcalls_locked(sock, callback, context, callback, context, 0);
1347 #else /* (defined(__arm__) || defined(__arm64__)) */
1348 	sock_setupcalls_locked(sock, callback, context, NULL, NULL, 0);
1349 #endif /* (defined(__arm__) || defined(__arm64__)) */
1350 	socket_unlock(sock, 1);
1351 
1352 	return 0;
1353 }
1354 
1355 errno_t
sock_setupcalls(socket_t sock,sock_upcall rcallback,void * rcontext,sock_upcall wcallback,void * wcontext)1356 sock_setupcalls(socket_t sock, sock_upcall rcallback, void *rcontext,
1357     sock_upcall wcallback, void *wcontext)
1358 {
1359 	if (sock == NULL) {
1360 		return EINVAL;
1361 	}
1362 
1363 	/*
1364 	 * Note that we don't wait for any in progress upcall to complete.
1365 	 */
1366 	socket_lock(sock, 1);
1367 	sock_setupcalls_locked(sock, rcallback, rcontext, wcallback, wcontext, 0);
1368 	socket_unlock(sock, 1);
1369 
1370 	return 0;
1371 }
1372 
1373 void
sock_catchevents_locked(socket_t sock,sock_evupcall ecallback,void * econtext,long emask)1374 sock_catchevents_locked(socket_t sock, sock_evupcall ecallback, void *econtext,
1375     long emask)
1376 {
1377 	socket_lock_assert_owned(sock);
1378 
1379 	/*
1380 	 * Note that we don't wait for any in progress upcall to complete.
1381 	 */
1382 	if (ecallback != NULL) {
1383 		sock->so_event = ecallback;
1384 		sock->so_eventarg = econtext;
1385 		sock->so_eventmask = (uint32_t)emask;
1386 	} else {
1387 		sock->so_event = sonullevent;
1388 		sock->so_eventarg = NULL;
1389 		sock->so_eventmask = 0;
1390 	}
1391 }
1392 
1393 errno_t
sock_catchevents(socket_t sock,sock_evupcall ecallback,void * econtext,long emask)1394 sock_catchevents(socket_t sock, sock_evupcall ecallback, void *econtext,
1395     long emask)
1396 {
1397 	if (sock == NULL) {
1398 		return EINVAL;
1399 	}
1400 
1401 	socket_lock(sock, 1);
1402 	sock_catchevents_locked(sock, ecallback, econtext, emask);
1403 	socket_unlock(sock, 1);
1404 
1405 	return 0;
1406 }
1407 
1408 /*
1409  * Returns true whether or not a socket belongs to the kernel.
1410  */
1411 int
sock_iskernel(socket_t so)1412 sock_iskernel(socket_t so)
1413 {
1414 	return so && so->last_pid == 0;
1415 }
1416