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