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