xref: /xnu-8792.61.2/bsd/kern/kpi_socketfilter.c (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
1*42e22086SApple OSS Distributions /*
2*42e22086SApple OSS Distributions  * Copyright (c) 2003-2021 Apple Inc. All rights reserved.
3*42e22086SApple OSS Distributions  *
4*42e22086SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*42e22086SApple OSS Distributions  *
6*42e22086SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*42e22086SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*42e22086SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*42e22086SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*42e22086SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*42e22086SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*42e22086SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*42e22086SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*42e22086SApple OSS Distributions  *
15*42e22086SApple OSS Distributions  * Please obtain a copy of the License at
16*42e22086SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*42e22086SApple OSS Distributions  *
18*42e22086SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*42e22086SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*42e22086SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*42e22086SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*42e22086SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*42e22086SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*42e22086SApple OSS Distributions  * limitations under the License.
25*42e22086SApple OSS Distributions  *
26*42e22086SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*42e22086SApple OSS Distributions  */
28*42e22086SApple OSS Distributions 
29*42e22086SApple OSS Distributions #include <sys/kpi_socketfilter.h>
30*42e22086SApple OSS Distributions 
31*42e22086SApple OSS Distributions #include <sys/socket.h>
32*42e22086SApple OSS Distributions #include <sys/param.h>
33*42e22086SApple OSS Distributions #include <sys/errno.h>
34*42e22086SApple OSS Distributions #include <sys/malloc.h>
35*42e22086SApple OSS Distributions #include <sys/protosw.h>
36*42e22086SApple OSS Distributions #include <sys/domain.h>
37*42e22086SApple OSS Distributions #include <sys/proc.h>
38*42e22086SApple OSS Distributions #include <kern/locks.h>
39*42e22086SApple OSS Distributions #include <kern/thread.h>
40*42e22086SApple OSS Distributions #include <kern/debug.h>
41*42e22086SApple OSS Distributions #include <net/kext_net.h>
42*42e22086SApple OSS Distributions #include <net/if.h>
43*42e22086SApple OSS Distributions #include <net/net_api_stats.h>
44*42e22086SApple OSS Distributions #if SKYWALK && defined(XNU_TARGET_OS_OSX)
45*42e22086SApple OSS Distributions #include <skywalk/lib/net_filter_event.h>
46*42e22086SApple OSS Distributions #endif /* SKYWALK && XNU_TARGET_OS_OSX */
47*42e22086SApple OSS Distributions #include <netinet/in_var.h>
48*42e22086SApple OSS Distributions #include <netinet/ip.h>
49*42e22086SApple OSS Distributions #include <netinet/ip_var.h>
50*42e22086SApple OSS Distributions #include <netinet/tcp.h>
51*42e22086SApple OSS Distributions #include <netinet/tcp_var.h>
52*42e22086SApple OSS Distributions #include <netinet/udp.h>
53*42e22086SApple OSS Distributions #include <netinet/udp_var.h>
54*42e22086SApple OSS Distributions 
55*42e22086SApple OSS Distributions #include <libkern/libkern.h>
56*42e22086SApple OSS Distributions #include <libkern/OSAtomic.h>
57*42e22086SApple OSS Distributions 
58*42e22086SApple OSS Distributions #include <libkern/sysctl.h>
59*42e22086SApple OSS Distributions #include <libkern/OSDebug.h>
60*42e22086SApple OSS Distributions 
61*42e22086SApple OSS Distributions #include <os/refcnt.h>
62*42e22086SApple OSS Distributions 
63*42e22086SApple OSS Distributions #include <stdbool.h>
64*42e22086SApple OSS Distributions #include <string.h>
65*42e22086SApple OSS Distributions 
66*42e22086SApple OSS Distributions #if SKYWALK
67*42e22086SApple OSS Distributions #include <skywalk/core/skywalk_var.h>
68*42e22086SApple OSS Distributions #endif /* SKYWALK */
69*42e22086SApple OSS Distributions 
70*42e22086SApple OSS Distributions #define SFEF_ATTACHED           0x1     /* SFE is on socket list */
71*42e22086SApple OSS Distributions #define SFEF_NODETACH           0x2     /* Detach should not be called */
72*42e22086SApple OSS Distributions #define SFEF_NOSOCKET           0x4     /* Socket is gone */
73*42e22086SApple OSS Distributions 
74*42e22086SApple OSS Distributions struct socket_filter_entry {
75*42e22086SApple OSS Distributions 	struct socket_filter_entry      *sfe_next_onsocket;
76*42e22086SApple OSS Distributions 	struct socket_filter_entry      *sfe_next_onfilter;
77*42e22086SApple OSS Distributions 	struct socket_filter_entry      *sfe_next_oncleanup;
78*42e22086SApple OSS Distributions 
79*42e22086SApple OSS Distributions 	struct socket_filter            *sfe_filter;
80*42e22086SApple OSS Distributions 	struct socket                   *sfe_socket;
81*42e22086SApple OSS Distributions 	void                            *sfe_cookie;
82*42e22086SApple OSS Distributions 
83*42e22086SApple OSS Distributions 	uint32_t                        sfe_flags;
84*42e22086SApple OSS Distributions 	int32_t                         sfe_refcount;
85*42e22086SApple OSS Distributions };
86*42e22086SApple OSS Distributions 
87*42e22086SApple OSS Distributions struct socket_filter {
88*42e22086SApple OSS Distributions 	TAILQ_ENTRY(socket_filter)      sf_protosw_next;
89*42e22086SApple OSS Distributions 	TAILQ_ENTRY(socket_filter)      sf_global_next;
90*42e22086SApple OSS Distributions 	struct socket_filter_entry      *sf_entry_head;
91*42e22086SApple OSS Distributions 
92*42e22086SApple OSS Distributions 	struct protosw                  *sf_proto;
93*42e22086SApple OSS Distributions 	struct sflt_filter              sf_filter;
94*42e22086SApple OSS Distributions 	struct os_refcnt                sf_refcount;
95*42e22086SApple OSS Distributions 	uint32_t                        sf_flags;
96*42e22086SApple OSS Distributions };
97*42e22086SApple OSS Distributions 
98*42e22086SApple OSS Distributions #define SFF_INTERNAL    0x1
99*42e22086SApple OSS Distributions 
100*42e22086SApple OSS Distributions TAILQ_HEAD(socket_filter_list, socket_filter);
101*42e22086SApple OSS Distributions 
102*42e22086SApple OSS Distributions static LCK_GRP_DECLARE(sock_filter_lock_grp, "socket filter lock");
103*42e22086SApple OSS Distributions static LCK_RW_DECLARE(sock_filter_lock, &sock_filter_lock_grp);
104*42e22086SApple OSS Distributions static LCK_MTX_DECLARE(sock_filter_cleanup_lock, &sock_filter_lock_grp);
105*42e22086SApple OSS Distributions 
106*42e22086SApple OSS Distributions static struct socket_filter_list        sock_filter_head =
107*42e22086SApple OSS Distributions     TAILQ_HEAD_INITIALIZER(sock_filter_head);
108*42e22086SApple OSS Distributions static struct socket_filter_entry       *sock_filter_cleanup_entries = NULL;
109*42e22086SApple OSS Distributions static thread_t                         sock_filter_cleanup_thread = NULL;
110*42e22086SApple OSS Distributions 
111*42e22086SApple OSS Distributions static void sflt_cleanup_thread(void *, wait_result_t);
112*42e22086SApple OSS Distributions static void sflt_detach_locked(struct socket_filter_entry *entry);
113*42e22086SApple OSS Distributions 
114*42e22086SApple OSS Distributions #undef sflt_register
115*42e22086SApple OSS Distributions static errno_t sflt_register_common(const struct sflt_filter *filter, int domain,
116*42e22086SApple OSS Distributions     int type, int protocol, bool is_internal);
117*42e22086SApple OSS Distributions errno_t sflt_register(const struct sflt_filter *filter, int domain,
118*42e22086SApple OSS Distributions     int type, int protocol);
119*42e22086SApple OSS Distributions 
120*42e22086SApple OSS Distributions #if SKYWALK && defined(XNU_TARGET_OS_OSX)
121*42e22086SApple OSS Distributions static bool net_check_compatible_sfltr(void);
122*42e22086SApple OSS Distributions bool net_check_compatible_alf(void);
123*42e22086SApple OSS Distributions static bool net_check_compatible_parental_controls(void);
124*42e22086SApple OSS Distributions #endif /* SKYWALK && XNU_TARGET_OS_OSX */
125*42e22086SApple OSS Distributions 
126*42e22086SApple OSS Distributions #pragma mark -- Internal State Management --
127*42e22086SApple OSS Distributions 
128*42e22086SApple OSS Distributions __private_extern__ int
sflt_permission_check(struct inpcb * inp)129*42e22086SApple OSS Distributions sflt_permission_check(struct inpcb *inp)
130*42e22086SApple OSS Distributions {
131*42e22086SApple OSS Distributions 	/* Only IPv4 or IPv6 sockets can bypass filters */
132*42e22086SApple OSS Distributions 	if (!(inp->inp_vflag & INP_IPV4) &&
133*42e22086SApple OSS Distributions 	    !(inp->inp_vflag & INP_IPV6)) {
134*42e22086SApple OSS Distributions 		return 0;
135*42e22086SApple OSS Distributions 	}
136*42e22086SApple OSS Distributions 	/* Sockets that have this entitlement bypass socket filters. */
137*42e22086SApple OSS Distributions 	if (INP_INTCOPROC_ALLOWED(inp)) {
138*42e22086SApple OSS Distributions 		return 1;
139*42e22086SApple OSS Distributions 	}
140*42e22086SApple OSS Distributions 	/* Sockets bound to an intcoproc interface bypass socket filters. */
141*42e22086SApple OSS Distributions 	if ((inp->inp_flags & INP_BOUND_IF) &&
142*42e22086SApple OSS Distributions 	    IFNET_IS_INTCOPROC(inp->inp_boundifp)) {
143*42e22086SApple OSS Distributions 		return 1;
144*42e22086SApple OSS Distributions 	}
145*42e22086SApple OSS Distributions #if NECP
146*42e22086SApple OSS Distributions 	/*
147*42e22086SApple OSS Distributions 	 * Make sure that the NECP policy is populated.
148*42e22086SApple OSS Distributions 	 * If result is not populated, the policy ID will be
149*42e22086SApple OSS Distributions 	 * NECP_KERNEL_POLICY_ID_NONE. Note that if the result
150*42e22086SApple OSS Distributions 	 * is populated, but there was no match, it will be
151*42e22086SApple OSS Distributions 	 * NECP_KERNEL_POLICY_ID_NO_MATCH.
152*42e22086SApple OSS Distributions 	 * Do not call inp_update_necp_policy() to avoid scoping
153*42e22086SApple OSS Distributions 	 * a socket prior to calls to bind().
154*42e22086SApple OSS Distributions 	 */
155*42e22086SApple OSS Distributions 	if (inp->inp_policyresult.policy_id == NECP_KERNEL_POLICY_ID_NONE) {
156*42e22086SApple OSS Distributions 		necp_socket_find_policy_match(inp, NULL, NULL, 0);
157*42e22086SApple OSS Distributions 	}
158*42e22086SApple OSS Distributions 
159*42e22086SApple OSS Distributions 	/* If the filter unit is marked to be "no filter", bypass filters */
160*42e22086SApple OSS Distributions 	if (inp->inp_policyresult.results.filter_control_unit ==
161*42e22086SApple OSS Distributions 	    NECP_FILTER_UNIT_NO_FILTER) {
162*42e22086SApple OSS Distributions 		return 1;
163*42e22086SApple OSS Distributions 	}
164*42e22086SApple OSS Distributions #endif /* NECP */
165*42e22086SApple OSS Distributions 	return 0;
166*42e22086SApple OSS Distributions }
167*42e22086SApple OSS Distributions 
168*42e22086SApple OSS Distributions static void
sflt_retain_locked(struct socket_filter * filter)169*42e22086SApple OSS Distributions sflt_retain_locked(struct socket_filter *filter)
170*42e22086SApple OSS Distributions {
171*42e22086SApple OSS Distributions 	os_ref_retain_locked(&filter->sf_refcount);
172*42e22086SApple OSS Distributions }
173*42e22086SApple OSS Distributions 
174*42e22086SApple OSS Distributions static void
sflt_release_locked(struct socket_filter * filter)175*42e22086SApple OSS Distributions sflt_release_locked(struct socket_filter *filter)
176*42e22086SApple OSS Distributions {
177*42e22086SApple OSS Distributions 	if (os_ref_release_locked(&filter->sf_refcount) == 0) {
178*42e22086SApple OSS Distributions 		/* Call the unregistered function */
179*42e22086SApple OSS Distributions 		if (filter->sf_filter.sf_unregistered) {
180*42e22086SApple OSS Distributions 			lck_rw_unlock_exclusive(&sock_filter_lock);
181*42e22086SApple OSS Distributions 			filter->sf_filter.sf_unregistered(
182*42e22086SApple OSS Distributions 				filter->sf_filter.sf_handle);
183*42e22086SApple OSS Distributions 			lck_rw_lock_exclusive(&sock_filter_lock);
184*42e22086SApple OSS Distributions 		}
185*42e22086SApple OSS Distributions 
186*42e22086SApple OSS Distributions 		/* Free the entry */
187*42e22086SApple OSS Distributions 		kfree_type(struct socket_filter, filter);
188*42e22086SApple OSS Distributions 	}
189*42e22086SApple OSS Distributions }
190*42e22086SApple OSS Distributions 
191*42e22086SApple OSS Distributions static void
sflt_entry_retain(struct socket_filter_entry * entry)192*42e22086SApple OSS Distributions sflt_entry_retain(struct socket_filter_entry *entry)
193*42e22086SApple OSS Distributions {
194*42e22086SApple OSS Distributions 	if (OSIncrementAtomic(&entry->sfe_refcount) <= 0) {
195*42e22086SApple OSS Distributions 		panic("sflt_entry_retain - sfe_refcount <= 0");
196*42e22086SApple OSS Distributions 		/* NOTREACHED */
197*42e22086SApple OSS Distributions 	}
198*42e22086SApple OSS Distributions }
199*42e22086SApple OSS Distributions 
200*42e22086SApple OSS Distributions static void
sflt_entry_release(struct socket_filter_entry * entry)201*42e22086SApple OSS Distributions sflt_entry_release(struct socket_filter_entry *entry)
202*42e22086SApple OSS Distributions {
203*42e22086SApple OSS Distributions 	SInt32 old = OSDecrementAtomic(&entry->sfe_refcount);
204*42e22086SApple OSS Distributions 	if (old == 1) {
205*42e22086SApple OSS Distributions 		/* That was the last reference */
206*42e22086SApple OSS Distributions 
207*42e22086SApple OSS Distributions 		/* Take the cleanup lock */
208*42e22086SApple OSS Distributions 		lck_mtx_lock(&sock_filter_cleanup_lock);
209*42e22086SApple OSS Distributions 
210*42e22086SApple OSS Distributions 		/* Put this item on the cleanup list */
211*42e22086SApple OSS Distributions 		entry->sfe_next_oncleanup = sock_filter_cleanup_entries;
212*42e22086SApple OSS Distributions 		sock_filter_cleanup_entries = entry;
213*42e22086SApple OSS Distributions 
214*42e22086SApple OSS Distributions 		/* If the item is the first item in the list */
215*42e22086SApple OSS Distributions 		if (entry->sfe_next_oncleanup == NULL) {
216*42e22086SApple OSS Distributions 			if (sock_filter_cleanup_thread == NULL) {
217*42e22086SApple OSS Distributions 				/* Create a thread */
218*42e22086SApple OSS Distributions 				kernel_thread_start(sflt_cleanup_thread,
219*42e22086SApple OSS Distributions 				    NULL, &sock_filter_cleanup_thread);
220*42e22086SApple OSS Distributions 			} else {
221*42e22086SApple OSS Distributions 				/* Wakeup the thread */
222*42e22086SApple OSS Distributions 				wakeup(&sock_filter_cleanup_entries);
223*42e22086SApple OSS Distributions 			}
224*42e22086SApple OSS Distributions 		}
225*42e22086SApple OSS Distributions 
226*42e22086SApple OSS Distributions 		/* Drop the cleanup lock */
227*42e22086SApple OSS Distributions 		lck_mtx_unlock(&sock_filter_cleanup_lock);
228*42e22086SApple OSS Distributions 	} else if (old <= 0) {
229*42e22086SApple OSS Distributions 		panic("sflt_entry_release - sfe_refcount (%d) <= 0",
230*42e22086SApple OSS Distributions 		    (int)old);
231*42e22086SApple OSS Distributions 		/* NOTREACHED */
232*42e22086SApple OSS Distributions 	}
233*42e22086SApple OSS Distributions }
234*42e22086SApple OSS Distributions 
235*42e22086SApple OSS Distributions __attribute__((noreturn))
236*42e22086SApple OSS Distributions static void
sflt_cleanup_thread(void * blah,wait_result_t blah2)237*42e22086SApple OSS Distributions sflt_cleanup_thread(void *blah, wait_result_t blah2)
238*42e22086SApple OSS Distributions {
239*42e22086SApple OSS Distributions #pragma unused(blah, blah2)
240*42e22086SApple OSS Distributions 	while (1) {
241*42e22086SApple OSS Distributions 		lck_mtx_lock(&sock_filter_cleanup_lock);
242*42e22086SApple OSS Distributions 		while (sock_filter_cleanup_entries == NULL) {
243*42e22086SApple OSS Distributions 			/* Sleep until we've got something better to do */
244*42e22086SApple OSS Distributions 			msleep(&sock_filter_cleanup_entries,
245*42e22086SApple OSS Distributions 			    &sock_filter_cleanup_lock, PWAIT,
246*42e22086SApple OSS Distributions 			    "sflt_cleanup", NULL);
247*42e22086SApple OSS Distributions 		}
248*42e22086SApple OSS Distributions 
249*42e22086SApple OSS Distributions 		/* Pull the current list of dead items */
250*42e22086SApple OSS Distributions 		struct socket_filter_entry *dead = sock_filter_cleanup_entries;
251*42e22086SApple OSS Distributions 		sock_filter_cleanup_entries = NULL;
252*42e22086SApple OSS Distributions 
253*42e22086SApple OSS Distributions 		/* Drop the lock */
254*42e22086SApple OSS Distributions 		lck_mtx_unlock(&sock_filter_cleanup_lock);
255*42e22086SApple OSS Distributions 
256*42e22086SApple OSS Distributions 		/* Take the socket filter lock */
257*42e22086SApple OSS Distributions 		lck_rw_lock_exclusive(&sock_filter_lock);
258*42e22086SApple OSS Distributions 
259*42e22086SApple OSS Distributions 		/* Cleanup every dead item */
260*42e22086SApple OSS Distributions 		struct socket_filter_entry      *entry;
261*42e22086SApple OSS Distributions 		for (entry = dead; entry; entry = dead) {
262*42e22086SApple OSS Distributions 			struct socket_filter_entry      **nextpp;
263*42e22086SApple OSS Distributions 
264*42e22086SApple OSS Distributions 			dead = entry->sfe_next_oncleanup;
265*42e22086SApple OSS Distributions 
266*42e22086SApple OSS Distributions 			/* Call detach function if necessary - drop the lock */
267*42e22086SApple OSS Distributions 			if ((entry->sfe_flags & SFEF_NODETACH) == 0 &&
268*42e22086SApple OSS Distributions 			    entry->sfe_filter->sf_filter.sf_detach) {
269*42e22086SApple OSS Distributions 				entry->sfe_flags |= SFEF_NODETACH;
270*42e22086SApple OSS Distributions 				lck_rw_unlock_exclusive(&sock_filter_lock);
271*42e22086SApple OSS Distributions 
272*42e22086SApple OSS Distributions 				/*
273*42e22086SApple OSS Distributions 				 * Warning - passing a potentially
274*42e22086SApple OSS Distributions 				 * dead socket may be bad
275*42e22086SApple OSS Distributions 				 */
276*42e22086SApple OSS Distributions 				entry->sfe_filter->sf_filter.sf_detach(
277*42e22086SApple OSS Distributions 					entry->sfe_cookie, entry->sfe_socket);
278*42e22086SApple OSS Distributions 
279*42e22086SApple OSS Distributions 				lck_rw_lock_exclusive(&sock_filter_lock);
280*42e22086SApple OSS Distributions 			}
281*42e22086SApple OSS Distributions 
282*42e22086SApple OSS Distributions 			/*
283*42e22086SApple OSS Distributions 			 * Pull entry off the socket list --
284*42e22086SApple OSS Distributions 			 * if the socket still exists
285*42e22086SApple OSS Distributions 			 */
286*42e22086SApple OSS Distributions 			if ((entry->sfe_flags & SFEF_NOSOCKET) == 0) {
287*42e22086SApple OSS Distributions 				for (nextpp = &entry->sfe_socket->so_filt;
288*42e22086SApple OSS Distributions 				    *nextpp;
289*42e22086SApple OSS Distributions 				    nextpp = &(*nextpp)->sfe_next_onsocket) {
290*42e22086SApple OSS Distributions 					if (*nextpp == entry) {
291*42e22086SApple OSS Distributions 						*nextpp =
292*42e22086SApple OSS Distributions 						    entry->sfe_next_onsocket;
293*42e22086SApple OSS Distributions 						break;
294*42e22086SApple OSS Distributions 					}
295*42e22086SApple OSS Distributions 				}
296*42e22086SApple OSS Distributions 			}
297*42e22086SApple OSS Distributions 
298*42e22086SApple OSS Distributions 			/* Pull entry off the filter list */
299*42e22086SApple OSS Distributions 			for (nextpp = &entry->sfe_filter->sf_entry_head;
300*42e22086SApple OSS Distributions 			    *nextpp; nextpp = &(*nextpp)->sfe_next_onfilter) {
301*42e22086SApple OSS Distributions 				if (*nextpp == entry) {
302*42e22086SApple OSS Distributions 					*nextpp = entry->sfe_next_onfilter;
303*42e22086SApple OSS Distributions 					break;
304*42e22086SApple OSS Distributions 				}
305*42e22086SApple OSS Distributions 			}
306*42e22086SApple OSS Distributions 
307*42e22086SApple OSS Distributions 			/*
308*42e22086SApple OSS Distributions 			 * Release the filter -- may drop lock, but that's okay
309*42e22086SApple OSS Distributions 			 */
310*42e22086SApple OSS Distributions 			sflt_release_locked(entry->sfe_filter);
311*42e22086SApple OSS Distributions 			entry->sfe_socket = NULL;
312*42e22086SApple OSS Distributions 			entry->sfe_filter = NULL;
313*42e22086SApple OSS Distributions 			kfree_type(struct socket_filter_entry, entry);
314*42e22086SApple OSS Distributions 		}
315*42e22086SApple OSS Distributions 
316*42e22086SApple OSS Distributions 		/* Drop the socket filter lock */
317*42e22086SApple OSS Distributions 		lck_rw_unlock_exclusive(&sock_filter_lock);
318*42e22086SApple OSS Distributions 	}
319*42e22086SApple OSS Distributions 	/* NOTREACHED */
320*42e22086SApple OSS Distributions }
321*42e22086SApple OSS Distributions 
322*42e22086SApple OSS Distributions static int
sflt_attach_locked(struct socket * so,struct socket_filter * filter,int socklocked)323*42e22086SApple OSS Distributions sflt_attach_locked(struct socket *so, struct socket_filter *filter,
324*42e22086SApple OSS Distributions     int socklocked)
325*42e22086SApple OSS Distributions {
326*42e22086SApple OSS Distributions 	int error = 0;
327*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry = NULL;
328*42e22086SApple OSS Distributions 
329*42e22086SApple OSS Distributions 	if (sflt_permission_check(sotoinpcb(so))) {
330*42e22086SApple OSS Distributions 		return 0;
331*42e22086SApple OSS Distributions 	}
332*42e22086SApple OSS Distributions 
333*42e22086SApple OSS Distributions 	if (filter == NULL) {
334*42e22086SApple OSS Distributions 		return ENOENT;
335*42e22086SApple OSS Distributions 	}
336*42e22086SApple OSS Distributions 
337*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry; entry = entry->sfe_next_onfilter) {
338*42e22086SApple OSS Distributions 		if (entry->sfe_filter->sf_filter.sf_handle ==
339*42e22086SApple OSS Distributions 		    filter->sf_filter.sf_handle) {
340*42e22086SApple OSS Distributions 			return EEXIST;
341*42e22086SApple OSS Distributions 		}
342*42e22086SApple OSS Distributions 	}
343*42e22086SApple OSS Distributions 	/* allocate the socket filter entry */
344*42e22086SApple OSS Distributions 	entry = kalloc_type(struct socket_filter_entry, Z_WAITOK | Z_NOFAIL);
345*42e22086SApple OSS Distributions 
346*42e22086SApple OSS Distributions 	/* Initialize the socket filter entry */
347*42e22086SApple OSS Distributions 	entry->sfe_cookie = NULL;
348*42e22086SApple OSS Distributions 	entry->sfe_flags = SFEF_ATTACHED;
349*42e22086SApple OSS Distributions 	entry->sfe_refcount = 1; /* corresponds to SFEF_ATTACHED flag set */
350*42e22086SApple OSS Distributions 
351*42e22086SApple OSS Distributions 	/* Put the entry in the filter list */
352*42e22086SApple OSS Distributions 	sflt_retain_locked(filter);
353*42e22086SApple OSS Distributions 	entry->sfe_filter = filter;
354*42e22086SApple OSS Distributions 	entry->sfe_next_onfilter = filter->sf_entry_head;
355*42e22086SApple OSS Distributions 	filter->sf_entry_head = entry;
356*42e22086SApple OSS Distributions 
357*42e22086SApple OSS Distributions 	/* Put the entry on the socket filter list */
358*42e22086SApple OSS Distributions 	entry->sfe_socket = so;
359*42e22086SApple OSS Distributions 	entry->sfe_next_onsocket = so->so_filt;
360*42e22086SApple OSS Distributions 	so->so_filt = entry;
361*42e22086SApple OSS Distributions 
362*42e22086SApple OSS Distributions 	if (entry->sfe_filter->sf_filter.sf_attach) {
363*42e22086SApple OSS Distributions 		/* Retain the entry while we call attach */
364*42e22086SApple OSS Distributions 		sflt_entry_retain(entry);
365*42e22086SApple OSS Distributions 
366*42e22086SApple OSS Distributions 		/*
367*42e22086SApple OSS Distributions 		 * Release the filter lock --
368*42e22086SApple OSS Distributions 		 * callers must be aware we will do this
369*42e22086SApple OSS Distributions 		 */
370*42e22086SApple OSS Distributions 		lck_rw_unlock_exclusive(&sock_filter_lock);
371*42e22086SApple OSS Distributions 
372*42e22086SApple OSS Distributions 		/* Unlock the socket */
373*42e22086SApple OSS Distributions 		if (socklocked) {
374*42e22086SApple OSS Distributions 			socket_unlock(so, 0);
375*42e22086SApple OSS Distributions 		}
376*42e22086SApple OSS Distributions 
377*42e22086SApple OSS Distributions 		/* It's finally safe to call the filter function */
378*42e22086SApple OSS Distributions 		error = entry->sfe_filter->sf_filter.sf_attach(
379*42e22086SApple OSS Distributions 			&entry->sfe_cookie, so);
380*42e22086SApple OSS Distributions 
381*42e22086SApple OSS Distributions 		/* Lock the socket again */
382*42e22086SApple OSS Distributions 		if (socklocked) {
383*42e22086SApple OSS Distributions 			socket_lock(so, 0);
384*42e22086SApple OSS Distributions 		}
385*42e22086SApple OSS Distributions 
386*42e22086SApple OSS Distributions 		/* Lock the filters again */
387*42e22086SApple OSS Distributions 		lck_rw_lock_exclusive(&sock_filter_lock);
388*42e22086SApple OSS Distributions 
389*42e22086SApple OSS Distributions 		/*
390*42e22086SApple OSS Distributions 		 * If the attach function returns an error,
391*42e22086SApple OSS Distributions 		 * this filter must be detached
392*42e22086SApple OSS Distributions 		 */
393*42e22086SApple OSS Distributions 		if (error) {
394*42e22086SApple OSS Distributions 			/* don't call sf_detach */
395*42e22086SApple OSS Distributions 			entry->sfe_flags |= SFEF_NODETACH;
396*42e22086SApple OSS Distributions 			sflt_detach_locked(entry);
397*42e22086SApple OSS Distributions 		}
398*42e22086SApple OSS Distributions 
399*42e22086SApple OSS Distributions 		/* Release the retain we held through the attach call */
400*42e22086SApple OSS Distributions 		sflt_entry_release(entry);
401*42e22086SApple OSS Distributions 	}
402*42e22086SApple OSS Distributions 
403*42e22086SApple OSS Distributions 	return error;
404*42e22086SApple OSS Distributions }
405*42e22086SApple OSS Distributions 
406*42e22086SApple OSS Distributions errno_t
sflt_attach_internal(socket_t socket,sflt_handle handle)407*42e22086SApple OSS Distributions sflt_attach_internal(socket_t socket, sflt_handle handle)
408*42e22086SApple OSS Distributions {
409*42e22086SApple OSS Distributions 	if (socket == NULL || handle == 0) {
410*42e22086SApple OSS Distributions 		return EINVAL;
411*42e22086SApple OSS Distributions 	}
412*42e22086SApple OSS Distributions 
413*42e22086SApple OSS Distributions 	int result = EINVAL;
414*42e22086SApple OSS Distributions 
415*42e22086SApple OSS Distributions 	lck_rw_lock_exclusive(&sock_filter_lock);
416*42e22086SApple OSS Distributions 
417*42e22086SApple OSS Distributions 	struct socket_filter *filter = NULL;
418*42e22086SApple OSS Distributions 	TAILQ_FOREACH(filter, &sock_filter_head, sf_global_next) {
419*42e22086SApple OSS Distributions 		if (filter->sf_filter.sf_handle == handle) {
420*42e22086SApple OSS Distributions 			break;
421*42e22086SApple OSS Distributions 		}
422*42e22086SApple OSS Distributions 	}
423*42e22086SApple OSS Distributions 
424*42e22086SApple OSS Distributions 	if (filter) {
425*42e22086SApple OSS Distributions 		result = sflt_attach_locked(socket, filter, 1);
426*42e22086SApple OSS Distributions 	}
427*42e22086SApple OSS Distributions 
428*42e22086SApple OSS Distributions 	lck_rw_unlock_exclusive(&sock_filter_lock);
429*42e22086SApple OSS Distributions 
430*42e22086SApple OSS Distributions 	return result;
431*42e22086SApple OSS Distributions }
432*42e22086SApple OSS Distributions 
433*42e22086SApple OSS Distributions static void
sflt_detach_locked(struct socket_filter_entry * entry)434*42e22086SApple OSS Distributions sflt_detach_locked(struct socket_filter_entry *entry)
435*42e22086SApple OSS Distributions {
436*42e22086SApple OSS Distributions 	if ((entry->sfe_flags & SFEF_ATTACHED) != 0) {
437*42e22086SApple OSS Distributions 		entry->sfe_flags &= ~SFEF_ATTACHED;
438*42e22086SApple OSS Distributions 		sflt_entry_release(entry);
439*42e22086SApple OSS Distributions 	}
440*42e22086SApple OSS Distributions }
441*42e22086SApple OSS Distributions 
442*42e22086SApple OSS Distributions #pragma mark -- Socket Layer Hooks --
443*42e22086SApple OSS Distributions 
444*42e22086SApple OSS Distributions __private_extern__ void
sflt_initsock(struct socket * so)445*42e22086SApple OSS Distributions sflt_initsock(struct socket *so)
446*42e22086SApple OSS Distributions {
447*42e22086SApple OSS Distributions 	/*
448*42e22086SApple OSS Distributions 	 * Can only register socket filter for internet protocols
449*42e22086SApple OSS Distributions 	 */
450*42e22086SApple OSS Distributions 	if (SOCK_DOM(so) != PF_INET && SOCK_DOM(so) != PF_INET6) {
451*42e22086SApple OSS Distributions 		return;
452*42e22086SApple OSS Distributions 	}
453*42e22086SApple OSS Distributions 
454*42e22086SApple OSS Distributions 	/*
455*42e22086SApple OSS Distributions 	 * Point to the real protosw, as so_proto might have been
456*42e22086SApple OSS Distributions 	 * pointed to a modified version.
457*42e22086SApple OSS Distributions 	 */
458*42e22086SApple OSS Distributions 	struct protosw *proto = so->so_proto->pr_protosw;
459*42e22086SApple OSS Distributions 
460*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
461*42e22086SApple OSS Distributions 	if (TAILQ_FIRST(&proto->pr_filter_head) != NULL) {
462*42e22086SApple OSS Distributions 		/* Promote lock to exclusive */
463*42e22086SApple OSS Distributions 		if (!lck_rw_lock_shared_to_exclusive(&sock_filter_lock)) {
464*42e22086SApple OSS Distributions 			lck_rw_lock_exclusive(&sock_filter_lock);
465*42e22086SApple OSS Distributions 		}
466*42e22086SApple OSS Distributions 
467*42e22086SApple OSS Distributions 		/*
468*42e22086SApple OSS Distributions 		 * Warning: A filter unregistering will be pulled out of
469*42e22086SApple OSS Distributions 		 * the list.  This could happen while we drop the lock in
470*42e22086SApple OSS Distributions 		 * sftl_attach_locked or sflt_release_locked.  For this
471*42e22086SApple OSS Distributions 		 * reason we retain a reference on the filter (or next_filter)
472*42e22086SApple OSS Distributions 		 * while calling this function.  This protects us from a panic,
473*42e22086SApple OSS Distributions 		 * but it could result in a socket being created without all
474*42e22086SApple OSS Distributions 		 * of the global filters if we're attaching a filter as it
475*42e22086SApple OSS Distributions 		 * is removed, if that's possible.
476*42e22086SApple OSS Distributions 		 */
477*42e22086SApple OSS Distributions 		struct socket_filter *filter =
478*42e22086SApple OSS Distributions 		    TAILQ_FIRST(&proto->pr_filter_head);
479*42e22086SApple OSS Distributions 
480*42e22086SApple OSS Distributions 		sflt_retain_locked(filter);
481*42e22086SApple OSS Distributions 
482*42e22086SApple OSS Distributions 		while (filter) {
483*42e22086SApple OSS Distributions 			struct socket_filter *filter_next;
484*42e22086SApple OSS Distributions 			/*
485*42e22086SApple OSS Distributions 			 * Warning: sflt_attach_private_locked
486*42e22086SApple OSS Distributions 			 * will drop the lock
487*42e22086SApple OSS Distributions 			 */
488*42e22086SApple OSS Distributions 			sflt_attach_locked(so, filter, 0);
489*42e22086SApple OSS Distributions 
490*42e22086SApple OSS Distributions 			filter_next = TAILQ_NEXT(filter, sf_protosw_next);
491*42e22086SApple OSS Distributions 			if (filter_next) {
492*42e22086SApple OSS Distributions 				sflt_retain_locked(filter_next);
493*42e22086SApple OSS Distributions 			}
494*42e22086SApple OSS Distributions 
495*42e22086SApple OSS Distributions 			/*
496*42e22086SApple OSS Distributions 			 * Warning: filt_release_locked may remove
497*42e22086SApple OSS Distributions 			 * the filter from the queue
498*42e22086SApple OSS Distributions 			 */
499*42e22086SApple OSS Distributions 			sflt_release_locked(filter);
500*42e22086SApple OSS Distributions 			filter = filter_next;
501*42e22086SApple OSS Distributions 		}
502*42e22086SApple OSS Distributions 	}
503*42e22086SApple OSS Distributions 	lck_rw_done(&sock_filter_lock);
504*42e22086SApple OSS Distributions }
505*42e22086SApple OSS Distributions 
506*42e22086SApple OSS Distributions /*
507*42e22086SApple OSS Distributions  * sflt_termsock
508*42e22086SApple OSS Distributions  *
509*42e22086SApple OSS Distributions  * Detaches all filters from the socket.
510*42e22086SApple OSS Distributions  */
511*42e22086SApple OSS Distributions __private_extern__ void
sflt_termsock(struct socket * so)512*42e22086SApple OSS Distributions sflt_termsock(struct socket *so)
513*42e22086SApple OSS Distributions {
514*42e22086SApple OSS Distributions 	/*
515*42e22086SApple OSS Distributions 	 * Fast path to avoid taking the lock
516*42e22086SApple OSS Distributions 	 */
517*42e22086SApple OSS Distributions 	if (so->so_filt == NULL) {
518*42e22086SApple OSS Distributions 		return;
519*42e22086SApple OSS Distributions 	}
520*42e22086SApple OSS Distributions 
521*42e22086SApple OSS Distributions 	lck_rw_lock_exclusive(&sock_filter_lock);
522*42e22086SApple OSS Distributions 
523*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
524*42e22086SApple OSS Distributions 
525*42e22086SApple OSS Distributions 	while ((entry = so->so_filt) != NULL) {
526*42e22086SApple OSS Distributions 		/* Pull filter off the socket */
527*42e22086SApple OSS Distributions 		so->so_filt = entry->sfe_next_onsocket;
528*42e22086SApple OSS Distributions 		entry->sfe_flags |= SFEF_NOSOCKET;
529*42e22086SApple OSS Distributions 
530*42e22086SApple OSS Distributions 		/* Call detach */
531*42e22086SApple OSS Distributions 		sflt_detach_locked(entry);
532*42e22086SApple OSS Distributions 
533*42e22086SApple OSS Distributions 		/*
534*42e22086SApple OSS Distributions 		 * On sflt_termsock, we can't return until the detach function
535*42e22086SApple OSS Distributions 		 * has been called.  Call the detach function - this is gross
536*42e22086SApple OSS Distributions 		 * because the socket filter entry could be freed when we drop
537*42e22086SApple OSS Distributions 		 * the lock, so we make copies on  the stack and retain
538*42e22086SApple OSS Distributions 		 * everything we need before dropping the lock.
539*42e22086SApple OSS Distributions 		 */
540*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_NODETACH) == 0 &&
541*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_detach) {
542*42e22086SApple OSS Distributions 			void *sfe_cookie = entry->sfe_cookie;
543*42e22086SApple OSS Distributions 			struct socket_filter *sfe_filter = entry->sfe_filter;
544*42e22086SApple OSS Distributions 
545*42e22086SApple OSS Distributions 			/* Retain the socket filter */
546*42e22086SApple OSS Distributions 			sflt_retain_locked(sfe_filter);
547*42e22086SApple OSS Distributions 
548*42e22086SApple OSS Distributions 			/* Mark that we've called the detach function */
549*42e22086SApple OSS Distributions 			entry->sfe_flags |= SFEF_NODETACH;
550*42e22086SApple OSS Distributions 
551*42e22086SApple OSS Distributions 			/* Drop the lock before calling the detach function */
552*42e22086SApple OSS Distributions 			lck_rw_unlock_exclusive(&sock_filter_lock);
553*42e22086SApple OSS Distributions 			sfe_filter->sf_filter.sf_detach(sfe_cookie, so);
554*42e22086SApple OSS Distributions 			lck_rw_lock_exclusive(&sock_filter_lock);
555*42e22086SApple OSS Distributions 
556*42e22086SApple OSS Distributions 			/* Release the filter */
557*42e22086SApple OSS Distributions 			sflt_release_locked(sfe_filter);
558*42e22086SApple OSS Distributions 		}
559*42e22086SApple OSS Distributions 	}
560*42e22086SApple OSS Distributions 
561*42e22086SApple OSS Distributions 	lck_rw_unlock_exclusive(&sock_filter_lock);
562*42e22086SApple OSS Distributions }
563*42e22086SApple OSS Distributions 
564*42e22086SApple OSS Distributions 
565*42e22086SApple OSS Distributions static void
sflt_notify_internal(struct socket * so,sflt_event_t event,void * param,sflt_handle handle)566*42e22086SApple OSS Distributions sflt_notify_internal(struct socket *so, sflt_event_t event, void *param,
567*42e22086SApple OSS Distributions     sflt_handle handle)
568*42e22086SApple OSS Distributions {
569*42e22086SApple OSS Distributions 	if (so->so_filt == NULL) {
570*42e22086SApple OSS Distributions 		return;
571*42e22086SApple OSS Distributions 	}
572*42e22086SApple OSS Distributions 
573*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
574*42e22086SApple OSS Distributions 	int unlocked = 0;
575*42e22086SApple OSS Distributions 
576*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
577*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry; entry = entry->sfe_next_onsocket) {
578*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
579*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_notify &&
580*42e22086SApple OSS Distributions 		    ((handle && entry->sfe_filter->sf_filter.sf_handle !=
581*42e22086SApple OSS Distributions 		    handle) || !handle)) {
582*42e22086SApple OSS Distributions 			/*
583*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
584*42e22086SApple OSS Distributions 			 * the socket filter lock
585*42e22086SApple OSS Distributions 			 */
586*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
587*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
588*42e22086SApple OSS Distributions 
589*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
590*42e22086SApple OSS Distributions 			if (unlocked == 0) {
591*42e22086SApple OSS Distributions 				unlocked = 1;
592*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
593*42e22086SApple OSS Distributions 			}
594*42e22086SApple OSS Distributions 
595*42e22086SApple OSS Distributions 			/* Finally call the filter */
596*42e22086SApple OSS Distributions 			entry->sfe_filter->sf_filter.sf_notify(
597*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, event, param);
598*42e22086SApple OSS Distributions 
599*42e22086SApple OSS Distributions 			/*
600*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
601*42e22086SApple OSS Distributions 			 * and release the entry
602*42e22086SApple OSS Distributions 			 */
603*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
604*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
605*42e22086SApple OSS Distributions 		}
606*42e22086SApple OSS Distributions 	}
607*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
608*42e22086SApple OSS Distributions 
609*42e22086SApple OSS Distributions 	if (unlocked != 0) {
610*42e22086SApple OSS Distributions 		socket_lock(so, 0);
611*42e22086SApple OSS Distributions 	}
612*42e22086SApple OSS Distributions }
613*42e22086SApple OSS Distributions 
614*42e22086SApple OSS Distributions __private_extern__ void
sflt_notify(struct socket * so,sflt_event_t event,void * param)615*42e22086SApple OSS Distributions sflt_notify(struct socket *so, sflt_event_t event, void  *param)
616*42e22086SApple OSS Distributions {
617*42e22086SApple OSS Distributions 	sflt_notify_internal(so, event, param, 0);
618*42e22086SApple OSS Distributions }
619*42e22086SApple OSS Distributions 
620*42e22086SApple OSS Distributions static void
sflt_notify_after_register(struct socket * so,sflt_event_t event,sflt_handle handle)621*42e22086SApple OSS Distributions sflt_notify_after_register(struct socket *so, sflt_event_t event,
622*42e22086SApple OSS Distributions     sflt_handle handle)
623*42e22086SApple OSS Distributions {
624*42e22086SApple OSS Distributions 	sflt_notify_internal(so, event, NULL, handle);
625*42e22086SApple OSS Distributions }
626*42e22086SApple OSS Distributions 
627*42e22086SApple OSS Distributions __private_extern__ int
sflt_ioctl(struct socket * so,u_long cmd,caddr_t data)628*42e22086SApple OSS Distributions sflt_ioctl(struct socket *so, u_long cmd, caddr_t data)
629*42e22086SApple OSS Distributions {
630*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
631*42e22086SApple OSS Distributions 		return 0;
632*42e22086SApple OSS Distributions 	}
633*42e22086SApple OSS Distributions 
634*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
635*42e22086SApple OSS Distributions 	int unlocked = 0;
636*42e22086SApple OSS Distributions 	int error = 0;
637*42e22086SApple OSS Distributions 
638*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
639*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
640*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
641*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
642*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_ioctl) {
643*42e22086SApple OSS Distributions 			/*
644*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
645*42e22086SApple OSS Distributions 			 * the socket filter lock
646*42e22086SApple OSS Distributions 			 */
647*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
648*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
649*42e22086SApple OSS Distributions 
650*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
651*42e22086SApple OSS Distributions 			if (unlocked == 0) {
652*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
653*42e22086SApple OSS Distributions 				unlocked = 1;
654*42e22086SApple OSS Distributions 			}
655*42e22086SApple OSS Distributions 
656*42e22086SApple OSS Distributions 			/* Call the filter */
657*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_ioctl(
658*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, cmd, data);
659*42e22086SApple OSS Distributions 
660*42e22086SApple OSS Distributions 			/*
661*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
662*42e22086SApple OSS Distributions 			 * and release the entry
663*42e22086SApple OSS Distributions 			 */
664*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
665*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
666*42e22086SApple OSS Distributions 		}
667*42e22086SApple OSS Distributions 	}
668*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
669*42e22086SApple OSS Distributions 
670*42e22086SApple OSS Distributions 	if (unlocked) {
671*42e22086SApple OSS Distributions 		socket_lock(so, 0);
672*42e22086SApple OSS Distributions 	}
673*42e22086SApple OSS Distributions 
674*42e22086SApple OSS Distributions 	return error;
675*42e22086SApple OSS Distributions }
676*42e22086SApple OSS Distributions 
677*42e22086SApple OSS Distributions __private_extern__ int
sflt_bind(struct socket * so,const struct sockaddr * nam)678*42e22086SApple OSS Distributions sflt_bind(struct socket *so, const struct sockaddr *nam)
679*42e22086SApple OSS Distributions {
680*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
681*42e22086SApple OSS Distributions 		return 0;
682*42e22086SApple OSS Distributions 	}
683*42e22086SApple OSS Distributions 
684*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
685*42e22086SApple OSS Distributions 	int unlocked = 0;
686*42e22086SApple OSS Distributions 	int error = 0;
687*42e22086SApple OSS Distributions 
688*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
689*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
690*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
691*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
692*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_bind) {
693*42e22086SApple OSS Distributions 			/*
694*42e22086SApple OSS Distributions 			 * Retain the filter entry and
695*42e22086SApple OSS Distributions 			 * release the socket filter lock
696*42e22086SApple OSS Distributions 			 */
697*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
698*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
699*42e22086SApple OSS Distributions 
700*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
701*42e22086SApple OSS Distributions 			if (unlocked == 0) {
702*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
703*42e22086SApple OSS Distributions 				unlocked = 1;
704*42e22086SApple OSS Distributions 			}
705*42e22086SApple OSS Distributions 
706*42e22086SApple OSS Distributions 			/* Call the filter */
707*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_bind(
708*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, nam);
709*42e22086SApple OSS Distributions 
710*42e22086SApple OSS Distributions 			/*
711*42e22086SApple OSS Distributions 			 * Take the socket filter lock again and
712*42e22086SApple OSS Distributions 			 * release the entry
713*42e22086SApple OSS Distributions 			 */
714*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
715*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
716*42e22086SApple OSS Distributions 		}
717*42e22086SApple OSS Distributions 	}
718*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
719*42e22086SApple OSS Distributions 
720*42e22086SApple OSS Distributions 	if (unlocked) {
721*42e22086SApple OSS Distributions 		socket_lock(so, 0);
722*42e22086SApple OSS Distributions 	}
723*42e22086SApple OSS Distributions 
724*42e22086SApple OSS Distributions 	return error;
725*42e22086SApple OSS Distributions }
726*42e22086SApple OSS Distributions 
727*42e22086SApple OSS Distributions __private_extern__ int
sflt_listen(struct socket * so)728*42e22086SApple OSS Distributions sflt_listen(struct socket *so)
729*42e22086SApple OSS Distributions {
730*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
731*42e22086SApple OSS Distributions 		return 0;
732*42e22086SApple OSS Distributions 	}
733*42e22086SApple OSS Distributions 
734*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
735*42e22086SApple OSS Distributions 	int unlocked = 0;
736*42e22086SApple OSS Distributions 	int error = 0;
737*42e22086SApple OSS Distributions 
738*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
739*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
740*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
741*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
742*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_listen) {
743*42e22086SApple OSS Distributions 			/*
744*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
745*42e22086SApple OSS Distributions 			 * the socket filter lock
746*42e22086SApple OSS Distributions 			 */
747*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
748*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
749*42e22086SApple OSS Distributions 
750*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
751*42e22086SApple OSS Distributions 			if (unlocked == 0) {
752*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
753*42e22086SApple OSS Distributions 				unlocked = 1;
754*42e22086SApple OSS Distributions 			}
755*42e22086SApple OSS Distributions 
756*42e22086SApple OSS Distributions 			/* Call the filter */
757*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_listen(
758*42e22086SApple OSS Distributions 				entry->sfe_cookie, so);
759*42e22086SApple OSS Distributions 
760*42e22086SApple OSS Distributions 			/*
761*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
762*42e22086SApple OSS Distributions 			 * and release the entry
763*42e22086SApple OSS Distributions 			 */
764*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
765*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
766*42e22086SApple OSS Distributions 		}
767*42e22086SApple OSS Distributions 	}
768*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
769*42e22086SApple OSS Distributions 
770*42e22086SApple OSS Distributions 	if (unlocked) {
771*42e22086SApple OSS Distributions 		socket_lock(so, 0);
772*42e22086SApple OSS Distributions 	}
773*42e22086SApple OSS Distributions 
774*42e22086SApple OSS Distributions 	return error;
775*42e22086SApple OSS Distributions }
776*42e22086SApple OSS Distributions 
777*42e22086SApple OSS Distributions __private_extern__ int
sflt_accept(struct socket * head,struct socket * so,const struct sockaddr * local,const struct sockaddr * remote)778*42e22086SApple OSS Distributions sflt_accept(struct socket *head, struct socket *so,
779*42e22086SApple OSS Distributions     const struct sockaddr *local, const struct sockaddr *remote)
780*42e22086SApple OSS Distributions {
781*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
782*42e22086SApple OSS Distributions 		return 0;
783*42e22086SApple OSS Distributions 	}
784*42e22086SApple OSS Distributions 
785*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
786*42e22086SApple OSS Distributions 	int unlocked = 0;
787*42e22086SApple OSS Distributions 	int error = 0;
788*42e22086SApple OSS Distributions 
789*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
790*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
791*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
792*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
793*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_accept) {
794*42e22086SApple OSS Distributions 			/*
795*42e22086SApple OSS Distributions 			 * Retain the filter entry and
796*42e22086SApple OSS Distributions 			 * release the socket filter lock
797*42e22086SApple OSS Distributions 			 */
798*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
799*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
800*42e22086SApple OSS Distributions 
801*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
802*42e22086SApple OSS Distributions 			if (unlocked == 0) {
803*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
804*42e22086SApple OSS Distributions 				unlocked = 1;
805*42e22086SApple OSS Distributions 			}
806*42e22086SApple OSS Distributions 
807*42e22086SApple OSS Distributions 			/* Call the filter */
808*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_accept(
809*42e22086SApple OSS Distributions 				entry->sfe_cookie, head, so, local, remote);
810*42e22086SApple OSS Distributions 
811*42e22086SApple OSS Distributions 			/*
812*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
813*42e22086SApple OSS Distributions 			 * and release the entry
814*42e22086SApple OSS Distributions 			 */
815*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
816*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
817*42e22086SApple OSS Distributions 		}
818*42e22086SApple OSS Distributions 	}
819*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
820*42e22086SApple OSS Distributions 
821*42e22086SApple OSS Distributions 	if (unlocked) {
822*42e22086SApple OSS Distributions 		socket_lock(so, 0);
823*42e22086SApple OSS Distributions 	}
824*42e22086SApple OSS Distributions 
825*42e22086SApple OSS Distributions 	return error;
826*42e22086SApple OSS Distributions }
827*42e22086SApple OSS Distributions 
828*42e22086SApple OSS Distributions __private_extern__ int
sflt_getsockname(struct socket * so,struct sockaddr ** local)829*42e22086SApple OSS Distributions sflt_getsockname(struct socket *so, struct sockaddr **local)
830*42e22086SApple OSS Distributions {
831*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
832*42e22086SApple OSS Distributions 		return 0;
833*42e22086SApple OSS Distributions 	}
834*42e22086SApple OSS Distributions 
835*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
836*42e22086SApple OSS Distributions 	int unlocked = 0;
837*42e22086SApple OSS Distributions 	int error = 0;
838*42e22086SApple OSS Distributions 
839*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
840*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
841*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
842*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
843*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_getsockname) {
844*42e22086SApple OSS Distributions 			/*
845*42e22086SApple OSS Distributions 			 * Retain the filter entry and
846*42e22086SApple OSS Distributions 			 * release the socket filter lock
847*42e22086SApple OSS Distributions 			 */
848*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
849*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
850*42e22086SApple OSS Distributions 
851*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
852*42e22086SApple OSS Distributions 			if (unlocked == 0) {
853*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
854*42e22086SApple OSS Distributions 				unlocked = 1;
855*42e22086SApple OSS Distributions 			}
856*42e22086SApple OSS Distributions 
857*42e22086SApple OSS Distributions 			/* Call the filter */
858*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_getsockname(
859*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, local);
860*42e22086SApple OSS Distributions 
861*42e22086SApple OSS Distributions 			/*
862*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
863*42e22086SApple OSS Distributions 			 * and release the entry
864*42e22086SApple OSS Distributions 			 */
865*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
866*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
867*42e22086SApple OSS Distributions 		}
868*42e22086SApple OSS Distributions 	}
869*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
870*42e22086SApple OSS Distributions 
871*42e22086SApple OSS Distributions 	if (unlocked) {
872*42e22086SApple OSS Distributions 		socket_lock(so, 0);
873*42e22086SApple OSS Distributions 	}
874*42e22086SApple OSS Distributions 
875*42e22086SApple OSS Distributions 	return error;
876*42e22086SApple OSS Distributions }
877*42e22086SApple OSS Distributions 
878*42e22086SApple OSS Distributions __private_extern__ int
sflt_getpeername(struct socket * so,struct sockaddr ** remote)879*42e22086SApple OSS Distributions sflt_getpeername(struct socket *so, struct sockaddr **remote)
880*42e22086SApple OSS Distributions {
881*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
882*42e22086SApple OSS Distributions 		return 0;
883*42e22086SApple OSS Distributions 	}
884*42e22086SApple OSS Distributions 
885*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
886*42e22086SApple OSS Distributions 	int unlocked = 0;
887*42e22086SApple OSS Distributions 	int error = 0;
888*42e22086SApple OSS Distributions 
889*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
890*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
891*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
892*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
893*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_getpeername) {
894*42e22086SApple OSS Distributions 			/*
895*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
896*42e22086SApple OSS Distributions 			 * the socket filter lock
897*42e22086SApple OSS Distributions 			 */
898*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
899*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
900*42e22086SApple OSS Distributions 
901*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
902*42e22086SApple OSS Distributions 			if (unlocked == 0) {
903*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
904*42e22086SApple OSS Distributions 				unlocked = 1;
905*42e22086SApple OSS Distributions 			}
906*42e22086SApple OSS Distributions 
907*42e22086SApple OSS Distributions 			/* Call the filter */
908*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_getpeername(
909*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, remote);
910*42e22086SApple OSS Distributions 
911*42e22086SApple OSS Distributions 			/*
912*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
913*42e22086SApple OSS Distributions 			 * and release the entry
914*42e22086SApple OSS Distributions 			 */
915*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
916*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
917*42e22086SApple OSS Distributions 		}
918*42e22086SApple OSS Distributions 	}
919*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
920*42e22086SApple OSS Distributions 
921*42e22086SApple OSS Distributions 	if (unlocked) {
922*42e22086SApple OSS Distributions 		socket_lock(so, 0);
923*42e22086SApple OSS Distributions 	}
924*42e22086SApple OSS Distributions 
925*42e22086SApple OSS Distributions 	return error;
926*42e22086SApple OSS Distributions }
927*42e22086SApple OSS Distributions 
928*42e22086SApple OSS Distributions __private_extern__ int
sflt_connectin(struct socket * so,const struct sockaddr * remote)929*42e22086SApple OSS Distributions sflt_connectin(struct socket *so, const struct sockaddr *remote)
930*42e22086SApple OSS Distributions {
931*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
932*42e22086SApple OSS Distributions 		return 0;
933*42e22086SApple OSS Distributions 	}
934*42e22086SApple OSS Distributions 
935*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
936*42e22086SApple OSS Distributions 	int unlocked = 0;
937*42e22086SApple OSS Distributions 	int error = 0;
938*42e22086SApple OSS Distributions 
939*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
940*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
941*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
942*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
943*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_connect_in) {
944*42e22086SApple OSS Distributions 			/*
945*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
946*42e22086SApple OSS Distributions 			 * the socket filter lock
947*42e22086SApple OSS Distributions 			 */
948*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
949*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
950*42e22086SApple OSS Distributions 
951*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
952*42e22086SApple OSS Distributions 			if (unlocked == 0) {
953*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
954*42e22086SApple OSS Distributions 				unlocked = 1;
955*42e22086SApple OSS Distributions 			}
956*42e22086SApple OSS Distributions 
957*42e22086SApple OSS Distributions 			/* Call the filter */
958*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_connect_in(
959*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, remote);
960*42e22086SApple OSS Distributions 
961*42e22086SApple OSS Distributions 			/*
962*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
963*42e22086SApple OSS Distributions 			 * and release the entry
964*42e22086SApple OSS Distributions 			 */
965*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
966*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
967*42e22086SApple OSS Distributions 		}
968*42e22086SApple OSS Distributions 	}
969*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
970*42e22086SApple OSS Distributions 
971*42e22086SApple OSS Distributions 	if (unlocked) {
972*42e22086SApple OSS Distributions 		socket_lock(so, 0);
973*42e22086SApple OSS Distributions 	}
974*42e22086SApple OSS Distributions 
975*42e22086SApple OSS Distributions 	return error;
976*42e22086SApple OSS Distributions }
977*42e22086SApple OSS Distributions 
978*42e22086SApple OSS Distributions static int
sflt_connectout_common(struct socket * so,const struct sockaddr * nam)979*42e22086SApple OSS Distributions sflt_connectout_common(struct socket *so, const struct sockaddr *nam)
980*42e22086SApple OSS Distributions {
981*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
982*42e22086SApple OSS Distributions 	int unlocked = 0;
983*42e22086SApple OSS Distributions 	int error = 0;
984*42e22086SApple OSS Distributions 
985*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
986*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
987*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
988*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
989*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_connect_out) {
990*42e22086SApple OSS Distributions 			/*
991*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
992*42e22086SApple OSS Distributions 			 * the socket filter lock
993*42e22086SApple OSS Distributions 			 */
994*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
995*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
996*42e22086SApple OSS Distributions 
997*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
998*42e22086SApple OSS Distributions 			if (unlocked == 0) {
999*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
1000*42e22086SApple OSS Distributions 				unlocked = 1;
1001*42e22086SApple OSS Distributions 			}
1002*42e22086SApple OSS Distributions 
1003*42e22086SApple OSS Distributions 			/* Call the filter */
1004*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_connect_out(
1005*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, nam);
1006*42e22086SApple OSS Distributions 
1007*42e22086SApple OSS Distributions 			/*
1008*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
1009*42e22086SApple OSS Distributions 			 * and release the entry
1010*42e22086SApple OSS Distributions 			 */
1011*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
1012*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
1013*42e22086SApple OSS Distributions 		}
1014*42e22086SApple OSS Distributions 	}
1015*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
1016*42e22086SApple OSS Distributions 
1017*42e22086SApple OSS Distributions 	if (unlocked) {
1018*42e22086SApple OSS Distributions 		socket_lock(so, 0);
1019*42e22086SApple OSS Distributions 	}
1020*42e22086SApple OSS Distributions 
1021*42e22086SApple OSS Distributions 	return error;
1022*42e22086SApple OSS Distributions }
1023*42e22086SApple OSS Distributions 
1024*42e22086SApple OSS Distributions __private_extern__ int
sflt_connectout(struct socket * so,const struct sockaddr * nam)1025*42e22086SApple OSS Distributions sflt_connectout(struct socket *so, const struct sockaddr *nam)
1026*42e22086SApple OSS Distributions {
1027*42e22086SApple OSS Distributions 	char buf[SOCK_MAXADDRLEN];
1028*42e22086SApple OSS Distributions 	struct sockaddr *sa;
1029*42e22086SApple OSS Distributions 	int error;
1030*42e22086SApple OSS Distributions 
1031*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
1032*42e22086SApple OSS Distributions 		return 0;
1033*42e22086SApple OSS Distributions 	}
1034*42e22086SApple OSS Distributions 
1035*42e22086SApple OSS Distributions 	/*
1036*42e22086SApple OSS Distributions 	 * Workaround for rdar://23362120
1037*42e22086SApple OSS Distributions 	 * Always pass a buffer that can hold an IPv6 socket address
1038*42e22086SApple OSS Distributions 	 */
1039*42e22086SApple OSS Distributions 	bzero(buf, sizeof(buf));
1040*42e22086SApple OSS Distributions 	bcopy(nam, buf, nam->sa_len);
1041*42e22086SApple OSS Distributions 	sa = (struct sockaddr *)buf;
1042*42e22086SApple OSS Distributions 
1043*42e22086SApple OSS Distributions 	error = sflt_connectout_common(so, sa);
1044*42e22086SApple OSS Distributions 	if (error != 0) {
1045*42e22086SApple OSS Distributions 		return error;
1046*42e22086SApple OSS Distributions 	}
1047*42e22086SApple OSS Distributions 
1048*42e22086SApple OSS Distributions 	/*
1049*42e22086SApple OSS Distributions 	 * If the address was modified, copy it back
1050*42e22086SApple OSS Distributions 	 */
1051*42e22086SApple OSS Distributions 	if (bcmp(sa, nam, nam->sa_len) != 0) {
1052*42e22086SApple OSS Distributions 		bcopy(sa, (struct sockaddr *)(uintptr_t)nam, nam->sa_len);
1053*42e22086SApple OSS Distributions 	}
1054*42e22086SApple OSS Distributions 
1055*42e22086SApple OSS Distributions 	return 0;
1056*42e22086SApple OSS Distributions }
1057*42e22086SApple OSS Distributions 
1058*42e22086SApple OSS Distributions __private_extern__ int
sflt_setsockopt(struct socket * so,struct sockopt * sopt)1059*42e22086SApple OSS Distributions sflt_setsockopt(struct socket *so, struct sockopt *sopt)
1060*42e22086SApple OSS Distributions {
1061*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
1062*42e22086SApple OSS Distributions 		return 0;
1063*42e22086SApple OSS Distributions 	}
1064*42e22086SApple OSS Distributions 
1065*42e22086SApple OSS Distributions 	/* Socket-options are checked at the MPTCP-layer */
1066*42e22086SApple OSS Distributions 	if (so->so_flags & SOF_MP_SUBFLOW) {
1067*42e22086SApple OSS Distributions 		return 0;
1068*42e22086SApple OSS Distributions 	}
1069*42e22086SApple OSS Distributions 
1070*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
1071*42e22086SApple OSS Distributions 	int unlocked = 0;
1072*42e22086SApple OSS Distributions 	int error = 0;
1073*42e22086SApple OSS Distributions 
1074*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
1075*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
1076*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
1077*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
1078*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_setoption) {
1079*42e22086SApple OSS Distributions 			/*
1080*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
1081*42e22086SApple OSS Distributions 			 * the socket filter lock
1082*42e22086SApple OSS Distributions 			 */
1083*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
1084*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
1085*42e22086SApple OSS Distributions 
1086*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
1087*42e22086SApple OSS Distributions 			if (unlocked == 0) {
1088*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
1089*42e22086SApple OSS Distributions 				unlocked = 1;
1090*42e22086SApple OSS Distributions 			}
1091*42e22086SApple OSS Distributions 
1092*42e22086SApple OSS Distributions 			/* Call the filter */
1093*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_setoption(
1094*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, sopt);
1095*42e22086SApple OSS Distributions 
1096*42e22086SApple OSS Distributions 			/*
1097*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
1098*42e22086SApple OSS Distributions 			 * and release the entry
1099*42e22086SApple OSS Distributions 			 */
1100*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
1101*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
1102*42e22086SApple OSS Distributions 		}
1103*42e22086SApple OSS Distributions 	}
1104*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
1105*42e22086SApple OSS Distributions 
1106*42e22086SApple OSS Distributions 	if (unlocked) {
1107*42e22086SApple OSS Distributions 		socket_lock(so, 0);
1108*42e22086SApple OSS Distributions 	}
1109*42e22086SApple OSS Distributions 
1110*42e22086SApple OSS Distributions 	return error;
1111*42e22086SApple OSS Distributions }
1112*42e22086SApple OSS Distributions 
1113*42e22086SApple OSS Distributions __private_extern__ int
sflt_getsockopt(struct socket * so,struct sockopt * sopt)1114*42e22086SApple OSS Distributions sflt_getsockopt(struct socket *so, struct sockopt *sopt)
1115*42e22086SApple OSS Distributions {
1116*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
1117*42e22086SApple OSS Distributions 		return 0;
1118*42e22086SApple OSS Distributions 	}
1119*42e22086SApple OSS Distributions 
1120*42e22086SApple OSS Distributions 	/* Socket-options are checked at the MPTCP-layer */
1121*42e22086SApple OSS Distributions 	if (so->so_flags & SOF_MP_SUBFLOW) {
1122*42e22086SApple OSS Distributions 		return 0;
1123*42e22086SApple OSS Distributions 	}
1124*42e22086SApple OSS Distributions 
1125*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
1126*42e22086SApple OSS Distributions 	int unlocked = 0;
1127*42e22086SApple OSS Distributions 	int error = 0;
1128*42e22086SApple OSS Distributions 
1129*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
1130*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
1131*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
1132*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
1133*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_getoption) {
1134*42e22086SApple OSS Distributions 			/*
1135*42e22086SApple OSS Distributions 			 * Retain the filter entry and release
1136*42e22086SApple OSS Distributions 			 * the socket filter lock
1137*42e22086SApple OSS Distributions 			 */
1138*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
1139*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
1140*42e22086SApple OSS Distributions 
1141*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
1142*42e22086SApple OSS Distributions 			if (unlocked == 0) {
1143*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
1144*42e22086SApple OSS Distributions 				unlocked = 1;
1145*42e22086SApple OSS Distributions 			}
1146*42e22086SApple OSS Distributions 
1147*42e22086SApple OSS Distributions 			/* Call the filter */
1148*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_getoption(
1149*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, sopt);
1150*42e22086SApple OSS Distributions 
1151*42e22086SApple OSS Distributions 			/*
1152*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
1153*42e22086SApple OSS Distributions 			 * and release the entry
1154*42e22086SApple OSS Distributions 			 */
1155*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
1156*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
1157*42e22086SApple OSS Distributions 		}
1158*42e22086SApple OSS Distributions 	}
1159*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
1160*42e22086SApple OSS Distributions 
1161*42e22086SApple OSS Distributions 	if (unlocked) {
1162*42e22086SApple OSS Distributions 		socket_lock(so, 0);
1163*42e22086SApple OSS Distributions 	}
1164*42e22086SApple OSS Distributions 
1165*42e22086SApple OSS Distributions 	return error;
1166*42e22086SApple OSS Distributions }
1167*42e22086SApple OSS Distributions 
1168*42e22086SApple OSS Distributions __private_extern__ int
sflt_data_out(struct socket * so,const struct sockaddr * to,mbuf_t * data,mbuf_t * control,sflt_data_flag_t flags)1169*42e22086SApple OSS Distributions sflt_data_out(struct socket *so, const struct sockaddr *to, mbuf_t *data,
1170*42e22086SApple OSS Distributions     mbuf_t *control, sflt_data_flag_t flags)
1171*42e22086SApple OSS Distributions {
1172*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
1173*42e22086SApple OSS Distributions 		return 0;
1174*42e22086SApple OSS Distributions 	}
1175*42e22086SApple OSS Distributions 
1176*42e22086SApple OSS Distributions 	/* Socket-options are checked at the MPTCP-layer */
1177*42e22086SApple OSS Distributions 	if (so->so_flags & SOF_MP_SUBFLOW) {
1178*42e22086SApple OSS Distributions 		return 0;
1179*42e22086SApple OSS Distributions 	}
1180*42e22086SApple OSS Distributions 
1181*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
1182*42e22086SApple OSS Distributions 	int unlocked = 0;
1183*42e22086SApple OSS Distributions 	int setsendthread = 0;
1184*42e22086SApple OSS Distributions 	int error = 0;
1185*42e22086SApple OSS Distributions 
1186*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
1187*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && error == 0;
1188*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
1189*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
1190*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_data_out) {
1191*42e22086SApple OSS Distributions 			/*
1192*42e22086SApple OSS Distributions 			 * Retain the filter entry and
1193*42e22086SApple OSS Distributions 			 * release the socket filter lock
1194*42e22086SApple OSS Distributions 			 */
1195*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
1196*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
1197*42e22086SApple OSS Distributions 
1198*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
1199*42e22086SApple OSS Distributions 			if (unlocked == 0) {
1200*42e22086SApple OSS Distributions 				if (so->so_send_filt_thread == NULL) {
1201*42e22086SApple OSS Distributions 					setsendthread = 1;
1202*42e22086SApple OSS Distributions 					so->so_send_filt_thread =
1203*42e22086SApple OSS Distributions 					    current_thread();
1204*42e22086SApple OSS Distributions 				}
1205*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
1206*42e22086SApple OSS Distributions 				unlocked = 1;
1207*42e22086SApple OSS Distributions 			}
1208*42e22086SApple OSS Distributions 
1209*42e22086SApple OSS Distributions 			/* Call the filter */
1210*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_data_out(
1211*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, to, data, control, flags);
1212*42e22086SApple OSS Distributions 
1213*42e22086SApple OSS Distributions 			/*
1214*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
1215*42e22086SApple OSS Distributions 			 * and release the entry
1216*42e22086SApple OSS Distributions 			 */
1217*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
1218*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
1219*42e22086SApple OSS Distributions 		}
1220*42e22086SApple OSS Distributions 	}
1221*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
1222*42e22086SApple OSS Distributions 
1223*42e22086SApple OSS Distributions 	if (unlocked) {
1224*42e22086SApple OSS Distributions 		socket_lock(so, 0);
1225*42e22086SApple OSS Distributions 		if (setsendthread) {
1226*42e22086SApple OSS Distributions 			so->so_send_filt_thread = NULL;
1227*42e22086SApple OSS Distributions 		}
1228*42e22086SApple OSS Distributions 	}
1229*42e22086SApple OSS Distributions 
1230*42e22086SApple OSS Distributions 	return error;
1231*42e22086SApple OSS Distributions }
1232*42e22086SApple OSS Distributions 
1233*42e22086SApple OSS Distributions __private_extern__ int
sflt_data_in(struct socket * so,const struct sockaddr * from,mbuf_t * data,mbuf_t * control,sflt_data_flag_t flags)1234*42e22086SApple OSS Distributions sflt_data_in(struct socket *so, const struct sockaddr *from, mbuf_t *data,
1235*42e22086SApple OSS Distributions     mbuf_t *control, sflt_data_flag_t flags)
1236*42e22086SApple OSS Distributions {
1237*42e22086SApple OSS Distributions 	if (so->so_filt == NULL || sflt_permission_check(sotoinpcb(so))) {
1238*42e22086SApple OSS Distributions 		return 0;
1239*42e22086SApple OSS Distributions 	}
1240*42e22086SApple OSS Distributions 
1241*42e22086SApple OSS Distributions 	/* Socket-options are checked at the MPTCP-layer */
1242*42e22086SApple OSS Distributions 	if (so->so_flags & SOF_MP_SUBFLOW) {
1243*42e22086SApple OSS Distributions 		return 0;
1244*42e22086SApple OSS Distributions 	}
1245*42e22086SApple OSS Distributions 
1246*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
1247*42e22086SApple OSS Distributions 	int error = 0;
1248*42e22086SApple OSS Distributions 	int unlocked = 0;
1249*42e22086SApple OSS Distributions 
1250*42e22086SApple OSS Distributions 	lck_rw_lock_shared(&sock_filter_lock);
1251*42e22086SApple OSS Distributions 
1252*42e22086SApple OSS Distributions 	for (entry = so->so_filt; entry && (error == 0);
1253*42e22086SApple OSS Distributions 	    entry = entry->sfe_next_onsocket) {
1254*42e22086SApple OSS Distributions 		if ((entry->sfe_flags & SFEF_ATTACHED) &&
1255*42e22086SApple OSS Distributions 		    entry->sfe_filter->sf_filter.sf_data_in) {
1256*42e22086SApple OSS Distributions 			/*
1257*42e22086SApple OSS Distributions 			 * Retain the filter entry and
1258*42e22086SApple OSS Distributions 			 * release the socket filter lock
1259*42e22086SApple OSS Distributions 			 */
1260*42e22086SApple OSS Distributions 			sflt_entry_retain(entry);
1261*42e22086SApple OSS Distributions 			lck_rw_unlock_shared(&sock_filter_lock);
1262*42e22086SApple OSS Distributions 
1263*42e22086SApple OSS Distributions 			/* If the socket isn't already unlocked, unlock it */
1264*42e22086SApple OSS Distributions 			if (unlocked == 0) {
1265*42e22086SApple OSS Distributions 				unlocked = 1;
1266*42e22086SApple OSS Distributions 				socket_unlock(so, 0);
1267*42e22086SApple OSS Distributions 			}
1268*42e22086SApple OSS Distributions 
1269*42e22086SApple OSS Distributions 			/* Call the filter */
1270*42e22086SApple OSS Distributions 			error = entry->sfe_filter->sf_filter.sf_data_in(
1271*42e22086SApple OSS Distributions 				entry->sfe_cookie, so, from, data, control, flags);
1272*42e22086SApple OSS Distributions 
1273*42e22086SApple OSS Distributions 			/*
1274*42e22086SApple OSS Distributions 			 * Take the socket filter lock again
1275*42e22086SApple OSS Distributions 			 * and release the entry
1276*42e22086SApple OSS Distributions 			 */
1277*42e22086SApple OSS Distributions 			lck_rw_lock_shared(&sock_filter_lock);
1278*42e22086SApple OSS Distributions 			sflt_entry_release(entry);
1279*42e22086SApple OSS Distributions 		}
1280*42e22086SApple OSS Distributions 	}
1281*42e22086SApple OSS Distributions 	lck_rw_unlock_shared(&sock_filter_lock);
1282*42e22086SApple OSS Distributions 
1283*42e22086SApple OSS Distributions 	if (unlocked) {
1284*42e22086SApple OSS Distributions 		socket_lock(so, 0);
1285*42e22086SApple OSS Distributions 	}
1286*42e22086SApple OSS Distributions 
1287*42e22086SApple OSS Distributions 	return error;
1288*42e22086SApple OSS Distributions }
1289*42e22086SApple OSS Distributions 
1290*42e22086SApple OSS Distributions #pragma mark -- KPI --
1291*42e22086SApple OSS Distributions 
1292*42e22086SApple OSS Distributions errno_t
sflt_attach(socket_t socket,sflt_handle handle)1293*42e22086SApple OSS Distributions sflt_attach(socket_t socket, sflt_handle handle)
1294*42e22086SApple OSS Distributions {
1295*42e22086SApple OSS Distributions 	socket_lock(socket, 1);
1296*42e22086SApple OSS Distributions 	errno_t result = sflt_attach_internal(socket, handle);
1297*42e22086SApple OSS Distributions 	socket_unlock(socket, 1);
1298*42e22086SApple OSS Distributions 	return result;
1299*42e22086SApple OSS Distributions }
1300*42e22086SApple OSS Distributions 
1301*42e22086SApple OSS Distributions errno_t
sflt_detach(socket_t socket,sflt_handle handle)1302*42e22086SApple OSS Distributions sflt_detach(socket_t socket, sflt_handle handle)
1303*42e22086SApple OSS Distributions {
1304*42e22086SApple OSS Distributions 	struct socket_filter_entry *entry;
1305*42e22086SApple OSS Distributions 	errno_t result = 0;
1306*42e22086SApple OSS Distributions 
1307*42e22086SApple OSS Distributions 	if (socket == NULL || handle == 0) {
1308*42e22086SApple OSS Distributions 		return EINVAL;
1309*42e22086SApple OSS Distributions 	}
1310*42e22086SApple OSS Distributions 
1311*42e22086SApple OSS Distributions 	lck_rw_lock_exclusive(&sock_filter_lock);
1312*42e22086SApple OSS Distributions 	for (entry = socket->so_filt; entry; entry = entry->sfe_next_onsocket) {
1313*42e22086SApple OSS Distributions 		if (entry->sfe_filter->sf_filter.sf_handle == handle &&
1314*42e22086SApple OSS Distributions 		    (entry->sfe_flags & SFEF_ATTACHED) != 0) {
1315*42e22086SApple OSS Distributions 			break;
1316*42e22086SApple OSS Distributions 		}
1317*42e22086SApple OSS Distributions 	}
1318*42e22086SApple OSS Distributions 
1319*42e22086SApple OSS Distributions 	if (entry != NULL) {
1320*42e22086SApple OSS Distributions 		sflt_detach_locked(entry);
1321*42e22086SApple OSS Distributions 	}
1322*42e22086SApple OSS Distributions 	lck_rw_unlock_exclusive(&sock_filter_lock);
1323*42e22086SApple OSS Distributions 
1324*42e22086SApple OSS Distributions 	return result;
1325*42e22086SApple OSS Distributions }
1326*42e22086SApple OSS Distributions 
1327*42e22086SApple OSS Distributions struct solist {
1328*42e22086SApple OSS Distributions 	struct solist *next;
1329*42e22086SApple OSS Distributions 	struct socket *so;
1330*42e22086SApple OSS Distributions };
1331*42e22086SApple OSS Distributions 
1332*42e22086SApple OSS Distributions static errno_t
sflt_register_common(const struct sflt_filter * filter,int domain,int type,int protocol,bool is_internal)1333*42e22086SApple OSS Distributions sflt_register_common(const struct sflt_filter *filter, int domain, int type,
1334*42e22086SApple OSS Distributions     int  protocol, bool is_internal)
1335*42e22086SApple OSS Distributions {
1336*42e22086SApple OSS Distributions 	struct socket_filter *sock_filt = NULL;
1337*42e22086SApple OSS Distributions 	struct socket_filter *match = NULL;
1338*42e22086SApple OSS Distributions 	int error = 0;
1339*42e22086SApple OSS Distributions 	struct protosw *pr;
1340*42e22086SApple OSS Distributions 	unsigned int len;
1341*42e22086SApple OSS Distributions 	struct socket *so;
1342*42e22086SApple OSS Distributions 	struct inpcb *inp;
1343*42e22086SApple OSS Distributions 	struct solist *solisthead = NULL, *solist = NULL;
1344*42e22086SApple OSS Distributions 
1345*42e22086SApple OSS Distributions 	if ((domain != PF_INET) && (domain != PF_INET6)) {
1346*42e22086SApple OSS Distributions 		return ENOTSUP;
1347*42e22086SApple OSS Distributions 	}
1348*42e22086SApple OSS Distributions 
1349*42e22086SApple OSS Distributions 	pr = pffindproto(domain, protocol, type);
1350*42e22086SApple OSS Distributions 	if (pr == NULL) {
1351*42e22086SApple OSS Distributions 		return ENOENT;
1352*42e22086SApple OSS Distributions 	}
1353*42e22086SApple OSS Distributions 
1354*42e22086SApple OSS Distributions 	if (filter->sf_attach == NULL || filter->sf_detach == NULL ||
1355*42e22086SApple OSS Distributions 	    filter->sf_handle == 0 || filter->sf_name == NULL) {
1356*42e22086SApple OSS Distributions 		return EINVAL;
1357*42e22086SApple OSS Distributions 	}
1358*42e22086SApple OSS Distributions 
1359*42e22086SApple OSS Distributions 	/* Allocate the socket filter */
1360*42e22086SApple OSS Distributions 	sock_filt = kalloc_type(struct socket_filter,
1361*42e22086SApple OSS Distributions 	    Z_WAITOK | Z_ZERO | Z_NOFAIL);
1362*42e22086SApple OSS Distributions 
1363*42e22086SApple OSS Distributions 	/* Legacy sflt_filter length; current structure minus extended */
1364*42e22086SApple OSS Distributions 	len = sizeof(*filter) - sizeof(struct sflt_filter_ext);
1365*42e22086SApple OSS Distributions 	/*
1366*42e22086SApple OSS Distributions 	 * Include extended fields if filter defines SFLT_EXTENDED.
1367*42e22086SApple OSS Distributions 	 * We've zeroed out our internal sflt_filter placeholder,
1368*42e22086SApple OSS Distributions 	 * so any unused portion would have been taken care of.
1369*42e22086SApple OSS Distributions 	 */
1370*42e22086SApple OSS Distributions 	if (filter->sf_flags & SFLT_EXTENDED) {
1371*42e22086SApple OSS Distributions 		unsigned int ext_len = filter->sf_len;
1372*42e22086SApple OSS Distributions 
1373*42e22086SApple OSS Distributions 		if (ext_len > sizeof(struct sflt_filter_ext)) {
1374*42e22086SApple OSS Distributions 			ext_len = sizeof(struct sflt_filter_ext);
1375*42e22086SApple OSS Distributions 		}
1376*42e22086SApple OSS Distributions 
1377*42e22086SApple OSS Distributions 		len += ext_len;
1378*42e22086SApple OSS Distributions 	}
1379*42e22086SApple OSS Distributions 	bcopy(filter, &sock_filt->sf_filter, len);
1380*42e22086SApple OSS Distributions 
1381*42e22086SApple OSS Distributions 	lck_rw_lock_exclusive(&sock_filter_lock);
1382*42e22086SApple OSS Distributions 	/* Look for an existing entry */
1383*42e22086SApple OSS Distributions 	TAILQ_FOREACH(match, &sock_filter_head, sf_global_next) {
1384*42e22086SApple OSS Distributions 		if (match->sf_filter.sf_handle ==
1385*42e22086SApple OSS Distributions 		    sock_filt->sf_filter.sf_handle) {
1386*42e22086SApple OSS Distributions 			break;
1387*42e22086SApple OSS Distributions 		}
1388*42e22086SApple OSS Distributions 	}
1389*42e22086SApple OSS Distributions 
1390*42e22086SApple OSS Distributions 	/* Add the entry only if there was no existing entry */
1391*42e22086SApple OSS Distributions 	if (match == NULL) {
1392*42e22086SApple OSS Distributions 		TAILQ_INSERT_TAIL(&sock_filter_head, sock_filt, sf_global_next);
1393*42e22086SApple OSS Distributions 		if ((sock_filt->sf_filter.sf_flags & SFLT_GLOBAL) != 0) {
1394*42e22086SApple OSS Distributions 			TAILQ_INSERT_TAIL(&pr->pr_filter_head, sock_filt,
1395*42e22086SApple OSS Distributions 			    sf_protosw_next);
1396*42e22086SApple OSS Distributions 			sock_filt->sf_proto = pr;
1397*42e22086SApple OSS Distributions 		}
1398*42e22086SApple OSS Distributions 		os_ref_init(&sock_filt->sf_refcount, NULL);
1399*42e22086SApple OSS Distributions 
1400*42e22086SApple OSS Distributions 		OSIncrementAtomic64(&net_api_stats.nas_sfltr_register_count);
1401*42e22086SApple OSS Distributions 		INC_ATOMIC_INT64_LIM(net_api_stats.nas_sfltr_register_total);
1402*42e22086SApple OSS Distributions 		if (is_internal) {
1403*42e22086SApple OSS Distributions 			sock_filt->sf_flags |= SFF_INTERNAL;
1404*42e22086SApple OSS Distributions 			OSIncrementAtomic64(&net_api_stats.nas_sfltr_register_os_count);
1405*42e22086SApple OSS Distributions 			INC_ATOMIC_INT64_LIM(net_api_stats.nas_sfltr_register_os_total);
1406*42e22086SApple OSS Distributions 		}
1407*42e22086SApple OSS Distributions 	}
1408*42e22086SApple OSS Distributions #if SKYWALK && defined(XNU_TARGET_OS_OSX)
1409*42e22086SApple OSS Distributions 	net_filter_event_mark(NET_FILTER_EVENT_SOCKET,
1410*42e22086SApple OSS Distributions 	    net_check_compatible_sfltr());
1411*42e22086SApple OSS Distributions 	net_filter_event_mark(NET_FILTER_EVENT_ALF,
1412*42e22086SApple OSS Distributions 	    net_check_compatible_alf());
1413*42e22086SApple OSS Distributions 	net_filter_event_mark(NET_FILTER_EVENT_PARENTAL_CONTROLS,
1414*42e22086SApple OSS Distributions 	    net_check_compatible_parental_controls());
1415*42e22086SApple OSS Distributions #endif /* SKYWALK && XNU_TARGET_OS_OSX */
1416*42e22086SApple OSS Distributions 
1417*42e22086SApple OSS Distributions 	lck_rw_unlock_exclusive(&sock_filter_lock);
1418*42e22086SApple OSS Distributions 
1419*42e22086SApple OSS Distributions 	if (match != NULL) {
1420*42e22086SApple OSS Distributions 		kfree_type(struct socket_filter, sock_filt);
1421*42e22086SApple OSS Distributions 		return EEXIST;
1422*42e22086SApple OSS Distributions 	}
1423*42e22086SApple OSS Distributions 
1424*42e22086SApple OSS Distributions 	if (!(filter->sf_flags & SFLT_EXTENDED_REGISTRY)) {
1425*42e22086SApple OSS Distributions 		return error;
1426*42e22086SApple OSS Distributions 	}
1427*42e22086SApple OSS Distributions 
1428*42e22086SApple OSS Distributions 	/*
1429*42e22086SApple OSS Distributions 	 * Setup the filter on the TCP and UDP sockets already created.
1430*42e22086SApple OSS Distributions 	 */
1431*42e22086SApple OSS Distributions #define SOLIST_ADD(_so) do {                                            \
1432*42e22086SApple OSS Distributions 	solist->next = solisthead;                                      \
1433*42e22086SApple OSS Distributions 	sock_retain((_so));                                             \
1434*42e22086SApple OSS Distributions 	solist->so = (_so);                                             \
1435*42e22086SApple OSS Distributions 	solisthead = solist;                                            \
1436*42e22086SApple OSS Distributions } while (0)
1437*42e22086SApple OSS Distributions 	if (protocol == IPPROTO_TCP) {
1438*42e22086SApple OSS Distributions 		lck_rw_lock_shared(&tcbinfo.ipi_lock);
1439*42e22086SApple OSS Distributions 		LIST_FOREACH(inp, tcbinfo.ipi_listhead, inp_list) {
1440*42e22086SApple OSS Distributions 			so = inp->inp_socket;
1441*42e22086SApple OSS Distributions 			if (so == NULL || (so->so_state & SS_DEFUNCT) ||
1442*42e22086SApple OSS Distributions 			    (!(so->so_flags & SOF_MP_SUBFLOW) &&
1443*42e22086SApple OSS Distributions 			    (so->so_state & SS_NOFDREF)) ||
1444*42e22086SApple OSS Distributions 			    !SOCK_CHECK_DOM(so, domain) ||
1445*42e22086SApple OSS Distributions 			    !SOCK_CHECK_TYPE(so, type)) {
1446*42e22086SApple OSS Distributions 				continue;
1447*42e22086SApple OSS Distributions 			}
1448*42e22086SApple OSS Distributions 			solist = kalloc_type(struct solist, Z_NOWAIT);
1449*42e22086SApple OSS Distributions 			if (!solist) {
1450*42e22086SApple OSS Distributions 				continue;
1451*42e22086SApple OSS Distributions 			}
1452*42e22086SApple OSS Distributions 			SOLIST_ADD(so);
1453*42e22086SApple OSS Distributions 		}
1454*42e22086SApple OSS Distributions 		lck_rw_done(&tcbinfo.ipi_lock);
1455*42e22086SApple OSS Distributions 	} else if (protocol == IPPROTO_UDP) {
1456*42e22086SApple OSS Distributions 		lck_rw_lock_shared(&udbinfo.ipi_lock);
1457*42e22086SApple OSS Distributions 		LIST_FOREACH(inp, udbinfo.ipi_listhead, inp_list) {
1458*42e22086SApple OSS Distributions 			so = inp->inp_socket;
1459*42e22086SApple OSS Distributions 			if (so == NULL || (so->so_state & SS_DEFUNCT) ||
1460*42e22086SApple OSS Distributions 			    (!(so->so_flags & SOF_MP_SUBFLOW) &&
1461*42e22086SApple OSS Distributions 			    (so->so_state & SS_NOFDREF)) ||
1462*42e22086SApple OSS Distributions 			    !SOCK_CHECK_DOM(so, domain) ||
1463*42e22086SApple OSS Distributions 			    !SOCK_CHECK_TYPE(so, type)) {
1464*42e22086SApple OSS Distributions 				continue;
1465*42e22086SApple OSS Distributions 			}
1466*42e22086SApple OSS Distributions 			solist = kalloc_type(struct solist, Z_NOWAIT);
1467*42e22086SApple OSS Distributions 			if (!solist) {
1468*42e22086SApple OSS Distributions 				continue;
1469*42e22086SApple OSS Distributions 			}
1470*42e22086SApple OSS Distributions 			SOLIST_ADD(so);
1471*42e22086SApple OSS Distributions 		}
1472*42e22086SApple OSS Distributions 		lck_rw_done(&udbinfo.ipi_lock);
1473*42e22086SApple OSS Distributions 	}
1474*42e22086SApple OSS Distributions 	/* XXX it's possible to walk the raw socket list as well */
1475*42e22086SApple OSS Distributions #undef SOLIST_ADD
1476*42e22086SApple OSS Distributions 
1477*42e22086SApple OSS Distributions 	while (solisthead) {
1478*42e22086SApple OSS Distributions 		sflt_handle handle = filter->sf_handle;
1479*42e22086SApple OSS Distributions 
1480*42e22086SApple OSS Distributions 		so = solisthead->so;
1481*42e22086SApple OSS Distributions 		socket_lock(so, 0);
1482*42e22086SApple OSS Distributions 		sflt_initsock(so);
1483*42e22086SApple OSS Distributions 		if (so->so_state & SS_ISCONNECTING) {
1484*42e22086SApple OSS Distributions 			sflt_notify_after_register(so, sock_evt_connecting,
1485*42e22086SApple OSS Distributions 			    handle);
1486*42e22086SApple OSS Distributions 		} else if (so->so_state & SS_ISCONNECTED) {
1487*42e22086SApple OSS Distributions 			sflt_notify_after_register(so, sock_evt_connected,
1488*42e22086SApple OSS Distributions 			    handle);
1489*42e22086SApple OSS Distributions 		} else if ((so->so_state &
1490*42e22086SApple OSS Distributions 		    (SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) ==
1491*42e22086SApple OSS Distributions 		    (SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) {
1492*42e22086SApple OSS Distributions 			sflt_notify_after_register(so, sock_evt_disconnecting,
1493*42e22086SApple OSS Distributions 			    handle);
1494*42e22086SApple OSS Distributions 		} else if ((so->so_state &
1495*42e22086SApple OSS Distributions 		    (SS_CANTRCVMORE | SS_CANTSENDMORE | SS_ISDISCONNECTED)) ==
1496*42e22086SApple OSS Distributions 		    (SS_CANTRCVMORE | SS_CANTSENDMORE | SS_ISDISCONNECTED)) {
1497*42e22086SApple OSS Distributions 			sflt_notify_after_register(so, sock_evt_disconnected,
1498*42e22086SApple OSS Distributions 			    handle);
1499*42e22086SApple OSS Distributions 		} else if (so->so_state & SS_CANTSENDMORE) {
1500*42e22086SApple OSS Distributions 			sflt_notify_after_register(so, sock_evt_cantsendmore,
1501*42e22086SApple OSS Distributions 			    handle);
1502*42e22086SApple OSS Distributions 		} else if (so->so_state & SS_CANTRCVMORE) {
1503*42e22086SApple OSS Distributions 			sflt_notify_after_register(so, sock_evt_cantrecvmore,
1504*42e22086SApple OSS Distributions 			    handle);
1505*42e22086SApple OSS Distributions 		}
1506*42e22086SApple OSS Distributions 		socket_unlock(so, 0);
1507*42e22086SApple OSS Distributions 		/* XXX no easy way to post the sock_evt_closing event */
1508*42e22086SApple OSS Distributions 		sock_release(so);
1509*42e22086SApple OSS Distributions 		solist = solisthead;
1510*42e22086SApple OSS Distributions 		solisthead = solisthead->next;
1511*42e22086SApple OSS Distributions 		kfree_type(struct solist, solist);
1512*42e22086SApple OSS Distributions 	}
1513*42e22086SApple OSS Distributions 
1514*42e22086SApple OSS Distributions 	return error;
1515*42e22086SApple OSS Distributions }
1516*42e22086SApple OSS Distributions 
1517*42e22086SApple OSS Distributions errno_t
sflt_register_internal(const struct sflt_filter * filter,int domain,int type,int protocol)1518*42e22086SApple OSS Distributions sflt_register_internal(const struct sflt_filter *filter, int domain, int type,
1519*42e22086SApple OSS Distributions     int  protocol)
1520*42e22086SApple OSS Distributions {
1521*42e22086SApple OSS Distributions 	return sflt_register_common(filter, domain, type, protocol, true);
1522*42e22086SApple OSS Distributions }
1523*42e22086SApple OSS Distributions 
1524*42e22086SApple OSS Distributions #define MAX_NUM_FRAMES 5
1525*42e22086SApple OSS Distributions 
1526*42e22086SApple OSS Distributions errno_t
sflt_register(const struct sflt_filter * filter,int domain,int type,int protocol)1527*42e22086SApple OSS Distributions sflt_register(const struct sflt_filter *filter, int domain, int type,
1528*42e22086SApple OSS Distributions     int  protocol)
1529*42e22086SApple OSS Distributions {
1530*42e22086SApple OSS Distributions 	return sflt_register_common(filter, domain, type, protocol, false);
1531*42e22086SApple OSS Distributions }
1532*42e22086SApple OSS Distributions 
1533*42e22086SApple OSS Distributions errno_t
sflt_unregister(sflt_handle handle)1534*42e22086SApple OSS Distributions sflt_unregister(sflt_handle handle)
1535*42e22086SApple OSS Distributions {
1536*42e22086SApple OSS Distributions 	struct socket_filter *filter;
1537*42e22086SApple OSS Distributions 	lck_rw_lock_exclusive(&sock_filter_lock);
1538*42e22086SApple OSS Distributions 
1539*42e22086SApple OSS Distributions 	/* Find the entry by the handle */
1540*42e22086SApple OSS Distributions 	TAILQ_FOREACH(filter, &sock_filter_head, sf_global_next) {
1541*42e22086SApple OSS Distributions 		if (filter->sf_filter.sf_handle == handle) {
1542*42e22086SApple OSS Distributions 			break;
1543*42e22086SApple OSS Distributions 		}
1544*42e22086SApple OSS Distributions 	}
1545*42e22086SApple OSS Distributions 
1546*42e22086SApple OSS Distributions 	if (filter) {
1547*42e22086SApple OSS Distributions 		if (filter->sf_flags & SFF_INTERNAL) {
1548*42e22086SApple OSS Distributions 			VERIFY(OSDecrementAtomic64(&net_api_stats.nas_sfltr_register_os_count) > 0);
1549*42e22086SApple OSS Distributions 		}
1550*42e22086SApple OSS Distributions 		VERIFY(OSDecrementAtomic64(&net_api_stats.nas_sfltr_register_count) > 0);
1551*42e22086SApple OSS Distributions 
1552*42e22086SApple OSS Distributions 		/* Remove it from the global list */
1553*42e22086SApple OSS Distributions 		TAILQ_REMOVE(&sock_filter_head, filter, sf_global_next);
1554*42e22086SApple OSS Distributions 
1555*42e22086SApple OSS Distributions 		/* Remove it from the protosw list */
1556*42e22086SApple OSS Distributions 		if ((filter->sf_filter.sf_flags & SFLT_GLOBAL) != 0) {
1557*42e22086SApple OSS Distributions 			TAILQ_REMOVE(&filter->sf_proto->pr_filter_head,
1558*42e22086SApple OSS Distributions 			    filter, sf_protosw_next);
1559*42e22086SApple OSS Distributions 		}
1560*42e22086SApple OSS Distributions 
1561*42e22086SApple OSS Distributions 		/* Detach from any sockets */
1562*42e22086SApple OSS Distributions 		struct socket_filter_entry *entry = NULL;
1563*42e22086SApple OSS Distributions 
1564*42e22086SApple OSS Distributions 		for (entry = filter->sf_entry_head; entry;
1565*42e22086SApple OSS Distributions 		    entry = entry->sfe_next_onfilter) {
1566*42e22086SApple OSS Distributions 			sflt_detach_locked(entry);
1567*42e22086SApple OSS Distributions 		}
1568*42e22086SApple OSS Distributions 
1569*42e22086SApple OSS Distributions 		/* Release the filter */
1570*42e22086SApple OSS Distributions 		sflt_release_locked(filter);
1571*42e22086SApple OSS Distributions 	}
1572*42e22086SApple OSS Distributions #if SKYWALK && defined(XNU_TARGET_OS_OSX)
1573*42e22086SApple OSS Distributions 	net_filter_event_mark(NET_FILTER_EVENT_SOCKET,
1574*42e22086SApple OSS Distributions 	    net_check_compatible_sfltr());
1575*42e22086SApple OSS Distributions 	net_filter_event_mark(NET_FILTER_EVENT_ALF,
1576*42e22086SApple OSS Distributions 	    net_check_compatible_alf());
1577*42e22086SApple OSS Distributions 	net_filter_event_mark(NET_FILTER_EVENT_PARENTAL_CONTROLS,
1578*42e22086SApple OSS Distributions 	    net_check_compatible_parental_controls());
1579*42e22086SApple OSS Distributions #endif /* SKYWALK && XNU_TARGET_OS_OSX */
1580*42e22086SApple OSS Distributions 
1581*42e22086SApple OSS Distributions 	lck_rw_unlock_exclusive(&sock_filter_lock);
1582*42e22086SApple OSS Distributions 
1583*42e22086SApple OSS Distributions 	if (filter == NULL) {
1584*42e22086SApple OSS Distributions 		return ENOENT;
1585*42e22086SApple OSS Distributions 	}
1586*42e22086SApple OSS Distributions 
1587*42e22086SApple OSS Distributions 	return 0;
1588*42e22086SApple OSS Distributions }
1589*42e22086SApple OSS Distributions 
1590*42e22086SApple OSS Distributions errno_t
sock_inject_data_in(socket_t so,const struct sockaddr * from,mbuf_t data,mbuf_t control,sflt_data_flag_t flags)1591*42e22086SApple OSS Distributions sock_inject_data_in(socket_t so, const struct sockaddr *from, mbuf_t data,
1592*42e22086SApple OSS Distributions     mbuf_t control, sflt_data_flag_t flags)
1593*42e22086SApple OSS Distributions {
1594*42e22086SApple OSS Distributions 	int error = 0;
1595*42e22086SApple OSS Distributions 
1596*42e22086SApple OSS Distributions 	if (so == NULL || data == NULL) {
1597*42e22086SApple OSS Distributions 		return EINVAL;
1598*42e22086SApple OSS Distributions 	}
1599*42e22086SApple OSS Distributions 
1600*42e22086SApple OSS Distributions 	if (flags & sock_data_filt_flag_oob) {
1601*42e22086SApple OSS Distributions 		return ENOTSUP;
1602*42e22086SApple OSS Distributions 	}
1603*42e22086SApple OSS Distributions 
1604*42e22086SApple OSS Distributions 	socket_lock(so, 1);
1605*42e22086SApple OSS Distributions 
1606*42e22086SApple OSS Distributions 	/* reject if this is a subflow socket */
1607*42e22086SApple OSS Distributions 	if (so->so_flags & SOF_MP_SUBFLOW) {
1608*42e22086SApple OSS Distributions 		error = ENOTSUP;
1609*42e22086SApple OSS Distributions 		goto done;
1610*42e22086SApple OSS Distributions 	}
1611*42e22086SApple OSS Distributions 
1612*42e22086SApple OSS Distributions 	if (from) {
1613*42e22086SApple OSS Distributions 		if (sbappendaddr(&so->so_rcv,
1614*42e22086SApple OSS Distributions 		    (struct sockaddr *)(uintptr_t)from, data, control, NULL)) {
1615*42e22086SApple OSS Distributions 			sorwakeup(so);
1616*42e22086SApple OSS Distributions 		}
1617*42e22086SApple OSS Distributions 		goto done;
1618*42e22086SApple OSS Distributions 	}
1619*42e22086SApple OSS Distributions 
1620*42e22086SApple OSS Distributions 	if (control) {
1621*42e22086SApple OSS Distributions 		if (sbappendcontrol(&so->so_rcv, data, control, NULL)) {
1622*42e22086SApple OSS Distributions 			sorwakeup(so);
1623*42e22086SApple OSS Distributions 		}
1624*42e22086SApple OSS Distributions 		goto done;
1625*42e22086SApple OSS Distributions 	}
1626*42e22086SApple OSS Distributions 
1627*42e22086SApple OSS Distributions 	if (flags & sock_data_filt_flag_record) {
1628*42e22086SApple OSS Distributions 		if (control || from) {
1629*42e22086SApple OSS Distributions 			error = EINVAL;
1630*42e22086SApple OSS Distributions 			goto done;
1631*42e22086SApple OSS Distributions 		}
1632*42e22086SApple OSS Distributions 		if (sbappendrecord(&so->so_rcv, (struct mbuf *)data)) {
1633*42e22086SApple OSS Distributions 			sorwakeup(so);
1634*42e22086SApple OSS Distributions 		}
1635*42e22086SApple OSS Distributions 		goto done;
1636*42e22086SApple OSS Distributions 	}
1637*42e22086SApple OSS Distributions 
1638*42e22086SApple OSS Distributions 	if (sbappend(&so->so_rcv, data)) {
1639*42e22086SApple OSS Distributions 		sorwakeup(so);
1640*42e22086SApple OSS Distributions 	}
1641*42e22086SApple OSS Distributions done:
1642*42e22086SApple OSS Distributions 	socket_unlock(so, 1);
1643*42e22086SApple OSS Distributions 	return error;
1644*42e22086SApple OSS Distributions }
1645*42e22086SApple OSS Distributions 
1646*42e22086SApple OSS Distributions errno_t
sock_inject_data_out(socket_t so,const struct sockaddr * to,mbuf_t data,mbuf_t control,sflt_data_flag_t flags)1647*42e22086SApple OSS Distributions sock_inject_data_out(socket_t so, const struct sockaddr *to, mbuf_t data,
1648*42e22086SApple OSS Distributions     mbuf_t control, sflt_data_flag_t flags)
1649*42e22086SApple OSS Distributions {
1650*42e22086SApple OSS Distributions 	int sosendflags = 0;
1651*42e22086SApple OSS Distributions 	int error = 0;
1652*42e22086SApple OSS Distributions 
1653*42e22086SApple OSS Distributions 	/* reject if this is a subflow socket */
1654*42e22086SApple OSS Distributions 	if (so->so_flags & SOF_MP_SUBFLOW) {
1655*42e22086SApple OSS Distributions 		return ENOTSUP;
1656*42e22086SApple OSS Distributions 	}
1657*42e22086SApple OSS Distributions 
1658*42e22086SApple OSS Distributions 	if (flags & sock_data_filt_flag_oob) {
1659*42e22086SApple OSS Distributions 		sosendflags = MSG_OOB;
1660*42e22086SApple OSS Distributions 	}
1661*42e22086SApple OSS Distributions 
1662*42e22086SApple OSS Distributions #if SKYWALK
1663*42e22086SApple OSS Distributions 	sk_protect_t protect = sk_async_transmit_protect();
1664*42e22086SApple OSS Distributions #endif /* SKYWALK */
1665*42e22086SApple OSS Distributions 
1666*42e22086SApple OSS Distributions 	error = sosend(so, (struct sockaddr *)(uintptr_t)to, NULL,
1667*42e22086SApple OSS Distributions 	    data, control, sosendflags);
1668*42e22086SApple OSS Distributions 
1669*42e22086SApple OSS Distributions #if SKYWALK
1670*42e22086SApple OSS Distributions 	sk_async_transmit_unprotect(protect);
1671*42e22086SApple OSS Distributions #endif /* SKYWALK */
1672*42e22086SApple OSS Distributions 
1673*42e22086SApple OSS Distributions 	return error;
1674*42e22086SApple OSS Distributions }
1675*42e22086SApple OSS Distributions 
1676*42e22086SApple OSS Distributions sockopt_dir
sockopt_direction(sockopt_t sopt)1677*42e22086SApple OSS Distributions sockopt_direction(sockopt_t sopt)
1678*42e22086SApple OSS Distributions {
1679*42e22086SApple OSS Distributions 	return (sopt->sopt_dir == SOPT_GET) ? sockopt_get : sockopt_set;
1680*42e22086SApple OSS Distributions }
1681*42e22086SApple OSS Distributions 
1682*42e22086SApple OSS Distributions int
sockopt_level(sockopt_t sopt)1683*42e22086SApple OSS Distributions sockopt_level(sockopt_t sopt)
1684*42e22086SApple OSS Distributions {
1685*42e22086SApple OSS Distributions 	return sopt->sopt_level;
1686*42e22086SApple OSS Distributions }
1687*42e22086SApple OSS Distributions 
1688*42e22086SApple OSS Distributions int
sockopt_name(sockopt_t sopt)1689*42e22086SApple OSS Distributions sockopt_name(sockopt_t sopt)
1690*42e22086SApple OSS Distributions {
1691*42e22086SApple OSS Distributions 	return sopt->sopt_name;
1692*42e22086SApple OSS Distributions }
1693*42e22086SApple OSS Distributions 
1694*42e22086SApple OSS Distributions size_t
sockopt_valsize(sockopt_t sopt)1695*42e22086SApple OSS Distributions sockopt_valsize(sockopt_t sopt)
1696*42e22086SApple OSS Distributions {
1697*42e22086SApple OSS Distributions 	return sopt->sopt_valsize;
1698*42e22086SApple OSS Distributions }
1699*42e22086SApple OSS Distributions 
1700*42e22086SApple OSS Distributions errno_t
sockopt_copyin(sockopt_t sopt,void * data,size_t len)1701*42e22086SApple OSS Distributions sockopt_copyin(sockopt_t sopt, void *data, size_t len)
1702*42e22086SApple OSS Distributions {
1703*42e22086SApple OSS Distributions 	return sooptcopyin(sopt, data, len, len);
1704*42e22086SApple OSS Distributions }
1705*42e22086SApple OSS Distributions 
1706*42e22086SApple OSS Distributions errno_t
sockopt_copyout(sockopt_t sopt,void * data,size_t len)1707*42e22086SApple OSS Distributions sockopt_copyout(sockopt_t sopt, void *data, size_t len)
1708*42e22086SApple OSS Distributions {
1709*42e22086SApple OSS Distributions 	return sooptcopyout(sopt, data, len);
1710*42e22086SApple OSS Distributions }
1711*42e22086SApple OSS Distributions 
1712*42e22086SApple OSS Distributions #if SKYWALK && defined(XNU_TARGET_OS_OSX)
1713*42e22086SApple OSS Distributions static bool
net_check_compatible_sfltr(void)1714*42e22086SApple OSS Distributions net_check_compatible_sfltr(void)
1715*42e22086SApple OSS Distributions {
1716*42e22086SApple OSS Distributions 	if (net_api_stats.nas_sfltr_register_count > net_api_stats.nas_sfltr_register_os_count ||
1717*42e22086SApple OSS Distributions 	    net_api_stats.nas_sfltr_register_os_count > 4) {
1718*42e22086SApple OSS Distributions 		return false;
1719*42e22086SApple OSS Distributions 	}
1720*42e22086SApple OSS Distributions 	return true;
1721*42e22086SApple OSS Distributions }
1722*42e22086SApple OSS Distributions 
1723*42e22086SApple OSS Distributions bool
net_check_compatible_alf(void)1724*42e22086SApple OSS Distributions net_check_compatible_alf(void)
1725*42e22086SApple OSS Distributions {
1726*42e22086SApple OSS Distributions 	int alf_perm;
1727*42e22086SApple OSS Distributions 	size_t len = sizeof(alf_perm);
1728*42e22086SApple OSS Distributions 	errno_t error;
1729*42e22086SApple OSS Distributions 
1730*42e22086SApple OSS Distributions 	error = kernel_sysctlbyname("net.alf.perm", &alf_perm, &len, NULL, 0);
1731*42e22086SApple OSS Distributions 	if (error == 0) {
1732*42e22086SApple OSS Distributions 		if (alf_perm != 0) {
1733*42e22086SApple OSS Distributions 			return false;
1734*42e22086SApple OSS Distributions 		}
1735*42e22086SApple OSS Distributions 	}
1736*42e22086SApple OSS Distributions 	return true;
1737*42e22086SApple OSS Distributions }
1738*42e22086SApple OSS Distributions 
1739*42e22086SApple OSS Distributions static bool
net_check_compatible_parental_controls(void)1740*42e22086SApple OSS Distributions net_check_compatible_parental_controls(void)
1741*42e22086SApple OSS Distributions {
1742*42e22086SApple OSS Distributions 	/*
1743*42e22086SApple OSS Distributions 	 * Assumes the first 4 OS socket filters are for ALF and additional
1744*42e22086SApple OSS Distributions 	 * OS filters are for Parental Controls web content filter
1745*42e22086SApple OSS Distributions 	 */
1746*42e22086SApple OSS Distributions 	if (net_api_stats.nas_sfltr_register_os_count > 4) {
1747*42e22086SApple OSS Distributions 		return false;
1748*42e22086SApple OSS Distributions 	}
1749*42e22086SApple OSS Distributions 	return true;
1750*42e22086SApple OSS Distributions }
1751*42e22086SApple OSS Distributions #endif /* SKYWALK && XNU_TARGET_OS_OSX */
1752