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