2 * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/kpi_socketfilter.h>
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>
36 #include <sys/domain.h>
38 #include <kern/locks.h>
39 #include <kern/thread.h>
40 #include <kern/debug.h>
41 #include <net/kext_net.h>
43 #include <netinet/in_var.h>
44 #include <netinet/ip.h>
45 #include <netinet/ip_var.h>
46 #include <netinet/tcp.h>
47 #include <netinet/tcp_var.h>
48 #include <netinet/udp.h>
49 #include <netinet/udp_var.h>
51 #include <libkern/libkern.h>
52 #include <libkern/OSAtomic.h>
56 #define SFEF_ATTACHED 0x1 /* SFE is on socket list */
57 #define SFEF_NODETACH 0x2 /* Detach should not be called */
58 #define SFEF_NOSOCKET 0x4 /* Socket is gone */
60 struct socket_filter_entry
{
61 struct socket_filter_entry
*sfe_next_onsocket
;
62 struct socket_filter_entry
*sfe_next_onfilter
;
63 struct socket_filter_entry
*sfe_next_oncleanup
;
65 struct socket_filter
*sfe_filter
;
66 struct socket
*sfe_socket
;
73 struct socket_filter
{
74 TAILQ_ENTRY(socket_filter
) sf_protosw_next
;
75 TAILQ_ENTRY(socket_filter
) sf_global_next
;
76 struct socket_filter_entry
*sf_entry_head
;
78 struct protosw
*sf_proto
;
79 struct sflt_filter sf_filter
;
80 u_int32_t sf_refcount
;
83 TAILQ_HEAD(socket_filter_list
, socket_filter
);
85 static struct socket_filter_list sock_filter_head
;
86 static lck_rw_t
*sock_filter_lock
= NULL
;
87 static lck_mtx_t
*sock_filter_cleanup_lock
= NULL
;
88 static struct socket_filter_entry
*sock_filter_cleanup_entries
= NULL
;
89 static thread_t sock_filter_cleanup_thread
= NULL
;
91 static void sflt_cleanup_thread(void *, wait_result_t
);
92 static void sflt_detach_locked(struct socket_filter_entry
*entry
);
94 #pragma mark -- Internal State Management --
96 __private_extern__
void
99 lck_grp_attr_t
*grp_attrib
= NULL
;
100 lck_attr_t
*lck_attrib
= NULL
;
101 lck_grp_t
*lck_group
= NULL
;
103 TAILQ_INIT(&sock_filter_head
);
105 /* Allocate a rw lock */
106 grp_attrib
= lck_grp_attr_alloc_init();
107 lck_group
= lck_grp_alloc_init("socket filter lock", grp_attrib
);
108 lck_grp_attr_free(grp_attrib
);
109 lck_attrib
= lck_attr_alloc_init();
110 sock_filter_lock
= lck_rw_alloc_init(lck_group
, lck_attrib
);
111 sock_filter_cleanup_lock
= lck_mtx_alloc_init(lck_group
, lck_attrib
);
112 lck_grp_free(lck_group
);
113 lck_attr_free(lck_attrib
);
117 sflt_retain_locked(struct socket_filter
*filter
)
119 filter
->sf_refcount
++;
123 sflt_release_locked(struct socket_filter
*filter
)
125 filter
->sf_refcount
--;
126 if (filter
->sf_refcount
== 0) {
127 /* Call the unregistered function */
128 if (filter
->sf_filter
.sf_unregistered
) {
129 lck_rw_unlock_exclusive(sock_filter_lock
);
130 filter
->sf_filter
.sf_unregistered(
131 filter
->sf_filter
.sf_handle
);
132 lck_rw_lock_exclusive(sock_filter_lock
);
136 FREE(filter
, M_IFADDR
);
141 sflt_entry_retain(struct socket_filter_entry
*entry
)
143 if (OSIncrementAtomic(&entry
->sfe_refcount
) <= 0) {
144 panic("sflt_entry_retain - sfe_refcount <= 0\n");
150 sflt_entry_release(struct socket_filter_entry
*entry
)
152 SInt32 old
= OSDecrementAtomic(&entry
->sfe_refcount
);
154 /* That was the last reference */
156 /* Take the cleanup lock */
157 lck_mtx_lock(sock_filter_cleanup_lock
);
159 /* Put this item on the cleanup list */
160 entry
->sfe_next_oncleanup
= sock_filter_cleanup_entries
;
161 sock_filter_cleanup_entries
= entry
;
163 /* If the item is the first item in the list */
164 if (entry
->sfe_next_oncleanup
== NULL
) {
165 if (sock_filter_cleanup_thread
== NULL
) {
166 /* Create a thread */
167 kernel_thread_start(sflt_cleanup_thread
,
168 NULL
, &sock_filter_cleanup_thread
);
170 /* Wakeup the thread */
171 wakeup(&sock_filter_cleanup_entries
);
175 /* Drop the cleanup lock */
176 lck_mtx_unlock(sock_filter_cleanup_lock
);
177 } else if (old
<= 0) {
178 panic("sflt_entry_release - sfe_refcount (%d) <= 0\n",
185 sflt_cleanup_thread(void *blah
, wait_result_t blah2
)
187 #pragma unused(blah, blah2)
189 lck_mtx_lock(sock_filter_cleanup_lock
);
190 while (sock_filter_cleanup_entries
== NULL
) {
191 /* Sleep until we've got something better to do */
192 msleep(&sock_filter_cleanup_entries
,
193 sock_filter_cleanup_lock
, PWAIT
,
194 "sflt_cleanup", NULL
);
197 /* Pull the current list of dead items */
198 struct socket_filter_entry
*dead
= sock_filter_cleanup_entries
;
199 sock_filter_cleanup_entries
= NULL
;
202 lck_mtx_unlock(sock_filter_cleanup_lock
);
204 /* Take the socket filter lock */
205 lck_rw_lock_exclusive(sock_filter_lock
);
207 /* Cleanup every dead item */
208 struct socket_filter_entry
*entry
;
209 for (entry
= dead
; entry
; entry
= dead
) {
210 struct socket_filter_entry
**nextpp
;
212 dead
= entry
->sfe_next_oncleanup
;
214 /* Call detach function if necessary - drop the lock */
215 if ((entry
->sfe_flags
& SFEF_NODETACH
) == 0 &&
216 entry
->sfe_filter
->sf_filter
.sf_detach
) {
217 entry
->sfe_flags
|= SFEF_NODETACH
;
218 lck_rw_unlock_exclusive(sock_filter_lock
);
221 * Warning - passing a potentially
222 * dead socket may be bad
224 entry
->sfe_filter
->sf_filter
. sf_detach(
225 entry
->sfe_cookie
, entry
->sfe_socket
);
227 lck_rw_lock_exclusive(sock_filter_lock
);
231 * Pull entry off the socket list --
232 * if the socket still exists
234 if ((entry
->sfe_flags
& SFEF_NOSOCKET
) == 0) {
235 for (nextpp
= &entry
->sfe_socket
->so_filt
;
237 nextpp
= &(*nextpp
)->sfe_next_onsocket
) {
238 if (*nextpp
== entry
) {
240 entry
->sfe_next_onsocket
;
246 /* Pull entry off the filter list */
247 for (nextpp
= &entry
->sfe_filter
->sf_entry_head
;
248 *nextpp
; nextpp
= &(*nextpp
)->sfe_next_onfilter
) {
249 if (*nextpp
== entry
) {
250 *nextpp
= entry
->sfe_next_onfilter
;
256 * Release the filter -- may drop lock, but that's okay
258 sflt_release_locked(entry
->sfe_filter
);
259 entry
->sfe_socket
= NULL
;
260 entry
->sfe_filter
= NULL
;
261 FREE(entry
, M_IFADDR
);
264 /* Drop the socket filter lock */
265 lck_rw_unlock_exclusive(sock_filter_lock
);
271 sflt_attach_locked(struct socket
*so
, struct socket_filter
*filter
,
275 struct socket_filter_entry
*entry
= NULL
;
280 for (entry
= so
->so_filt
; entry
; entry
= entry
->sfe_next_onfilter
) {
281 if (entry
->sfe_filter
->sf_filter
.sf_handle
==
282 filter
->sf_filter
.sf_handle
)
285 /* allocate the socket filter entry */
286 MALLOC(entry
, struct socket_filter_entry
*, sizeof (*entry
), M_IFADDR
,
291 /* Initialize the socket filter entry */
292 entry
->sfe_cookie
= NULL
;
293 entry
->sfe_flags
= SFEF_ATTACHED
;
294 entry
->sfe_refcount
= 1; /* corresponds to SFEF_ATTACHED flag set */
296 /* Put the entry in the filter list */
297 sflt_retain_locked(filter
);
298 entry
->sfe_filter
= filter
;
299 entry
->sfe_next_onfilter
= filter
->sf_entry_head
;
300 filter
->sf_entry_head
= entry
;
302 /* Put the entry on the socket filter list */
303 entry
->sfe_socket
= so
;
304 entry
->sfe_next_onsocket
= so
->so_filt
;
307 if (entry
->sfe_filter
->sf_filter
.sf_attach
) {
308 /* Retain the entry while we call attach */
309 sflt_entry_retain(entry
);
312 * Release the filter lock --
313 * callers must be aware we will do this
315 lck_rw_unlock_exclusive(sock_filter_lock
);
317 /* Unlock the socket */
319 socket_unlock(so
, 0);
321 /* It's finally safe to call the filter function */
322 error
= entry
->sfe_filter
->sf_filter
.sf_attach(
323 &entry
->sfe_cookie
, so
);
325 /* Lock the socket again */
329 /* Lock the filters again */
330 lck_rw_lock_exclusive(sock_filter_lock
);
333 * If the attach function returns an error,
334 * this filter must be detached
337 /* don't call sf_detach */
338 entry
->sfe_flags
|= SFEF_NODETACH
;
339 sflt_detach_locked(entry
);
342 /* Release the retain we held through the attach call */
343 sflt_entry_release(entry
);
350 sflt_attach_internal(socket_t socket
, sflt_handle handle
)
352 if (socket
== NULL
|| handle
== 0)
357 lck_rw_lock_exclusive(sock_filter_lock
);
359 struct socket_filter
*filter
= NULL
;
360 TAILQ_FOREACH(filter
, &sock_filter_head
, sf_global_next
) {
361 if (filter
->sf_filter
.sf_handle
== handle
) break;
365 result
= sflt_attach_locked(socket
, filter
, 1);
368 lck_rw_unlock_exclusive(sock_filter_lock
);
374 sflt_detach_locked(struct socket_filter_entry
*entry
)
376 if ((entry
->sfe_flags
& SFEF_ATTACHED
) != 0) {
377 entry
->sfe_flags
&= ~SFEF_ATTACHED
;
378 sflt_entry_release(entry
);
382 #pragma mark -- Socket Layer Hooks --
384 __private_extern__
void
385 sflt_initsock(struct socket
*so
)
388 * Point to the real protosw, as so_proto might have been
389 * pointed to a modified version.
391 struct protosw
*proto
= so
->so_proto
->pr_protosw
;
393 lck_rw_lock_shared(sock_filter_lock
);
394 if (TAILQ_FIRST(&proto
->pr_filter_head
) != NULL
) {
395 /* Promote lock to exclusive */
396 if (!lck_rw_lock_shared_to_exclusive(sock_filter_lock
))
397 lck_rw_lock_exclusive(sock_filter_lock
);
400 * Warning: A filter unregistering will be pulled out of
401 * the list. This could happen while we drop the lock in
402 * sftl_attach_locked or sflt_release_locked. For this
403 * reason we retain a reference on the filter (or next_filter)
404 * while calling this function. This protects us from a panic,
405 * but it could result in a socket being created without all
406 * of the global filters if we're attaching a filter as it
407 * is removed, if that's possible.
409 struct socket_filter
*filter
=
410 TAILQ_FIRST(&proto
->pr_filter_head
);
412 sflt_retain_locked(filter
);
415 struct socket_filter
*filter_next
;
417 * Warning: sflt_attach_private_locked
420 sflt_attach_locked(so
, filter
, 0);
422 filter_next
= TAILQ_NEXT(filter
, sf_protosw_next
);
424 sflt_retain_locked(filter_next
);
427 * Warning: filt_release_locked may remove
428 * the filter from the queue
430 sflt_release_locked(filter
);
431 filter
= filter_next
;
434 lck_rw_done(sock_filter_lock
);
440 * Detaches all filters from the socket.
442 __private_extern__
void
443 sflt_termsock(struct socket
*so
)
445 lck_rw_lock_exclusive(sock_filter_lock
);
447 struct socket_filter_entry
*entry
;
449 while ((entry
= so
->so_filt
) != NULL
) {
450 /* Pull filter off the socket */
451 so
->so_filt
= entry
->sfe_next_onsocket
;
452 entry
->sfe_flags
|= SFEF_NOSOCKET
;
455 sflt_detach_locked(entry
);
458 * On sflt_termsock, we can't return until the detach function
459 * has been called. Call the detach function - this is gross
460 * because the socket filter entry could be freed when we drop
461 * the lock, so we make copies on the stack and retain
462 * everything we need before dropping the lock.
464 if ((entry
->sfe_flags
& SFEF_NODETACH
) == 0 &&
465 entry
->sfe_filter
->sf_filter
.sf_detach
) {
466 void *sfe_cookie
= entry
->sfe_cookie
;
467 struct socket_filter
*sfe_filter
= entry
->sfe_filter
;
469 /* Retain the socket filter */
470 sflt_retain_locked(sfe_filter
);
472 /* Mark that we've called the detach function */
473 entry
->sfe_flags
|= SFEF_NODETACH
;
475 /* Drop the lock before calling the detach function */
476 lck_rw_unlock_exclusive(sock_filter_lock
);
477 sfe_filter
->sf_filter
.sf_detach(sfe_cookie
, so
);
478 lck_rw_lock_exclusive(sock_filter_lock
);
480 /* Release the filter */
481 sflt_release_locked(sfe_filter
);
485 lck_rw_unlock_exclusive(sock_filter_lock
);
490 sflt_notify_internal(struct socket
*so
, sflt_event_t event
, void *param
,
493 if (so
->so_filt
== NULL
)
496 struct socket_filter_entry
*entry
;
499 lck_rw_lock_shared(sock_filter_lock
);
500 for (entry
= so
->so_filt
; entry
; entry
= entry
->sfe_next_onsocket
) {
501 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
502 entry
->sfe_filter
->sf_filter
.sf_notify
&&
503 ((handle
&& entry
->sfe_filter
->sf_filter
.sf_handle
!=
504 handle
) || !handle
)) {
506 * Retain the filter entry and release
507 * the socket filter lock
509 sflt_entry_retain(entry
);
510 lck_rw_unlock_shared(sock_filter_lock
);
512 /* If the socket isn't already unlocked, unlock it */
515 socket_unlock(so
, 0);
518 /* Finally call the filter */
519 entry
->sfe_filter
->sf_filter
.sf_notify(
520 entry
->sfe_cookie
, so
, event
, param
);
523 * Take the socket filter lock again
524 * and release the entry
526 lck_rw_lock_shared(sock_filter_lock
);
527 sflt_entry_release(entry
);
530 lck_rw_unlock_shared(sock_filter_lock
);
537 __private_extern__
void
538 sflt_notify(struct socket
*so
, sflt_event_t event
, void *param
)
540 sflt_notify_internal(so
, event
, param
, 0);
544 sflt_notify_after_register(struct socket
*so
, sflt_event_t event
,
547 sflt_notify_internal(so
, event
, NULL
, handle
);
550 __private_extern__
int
551 sflt_ioctl(struct socket
*so
, u_long cmd
, caddr_t data
)
553 if (so
->so_filt
== NULL
)
556 struct socket_filter_entry
*entry
;
560 lck_rw_lock_shared(sock_filter_lock
);
561 for (entry
= so
->so_filt
; entry
&& error
== 0;
562 entry
= entry
->sfe_next_onsocket
) {
563 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
564 entry
->sfe_filter
->sf_filter
.sf_ioctl
) {
566 * Retain the filter entry and release
567 * the socket filter lock
569 sflt_entry_retain(entry
);
570 lck_rw_unlock_shared(sock_filter_lock
);
572 /* If the socket isn't already unlocked, unlock it */
574 socket_unlock(so
, 0);
578 /* Call the filter */
579 error
= entry
->sfe_filter
->sf_filter
.sf_ioctl(
580 entry
->sfe_cookie
, so
, cmd
, data
);
583 * Take the socket filter lock again
584 * and release the entry
586 lck_rw_lock_shared(sock_filter_lock
);
587 sflt_entry_release(entry
);
590 lck_rw_unlock_shared(sock_filter_lock
);
599 __private_extern__
int
600 sflt_bind(struct socket
*so
, const struct sockaddr
*nam
)
602 if (so
->so_filt
== NULL
)
605 struct socket_filter_entry
*entry
;
609 lck_rw_lock_shared(sock_filter_lock
);
610 for (entry
= so
->so_filt
; entry
&& error
== 0;
611 entry
= entry
->sfe_next_onsocket
) {
612 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
613 entry
->sfe_filter
->sf_filter
.sf_bind
) {
615 * Retain the filter entry and
616 * release the socket filter lock
618 sflt_entry_retain(entry
);
619 lck_rw_unlock_shared(sock_filter_lock
);
621 /* If the socket isn't already unlocked, unlock it */
623 socket_unlock(so
, 0);
627 /* Call the filter */
628 error
= entry
->sfe_filter
->sf_filter
.sf_bind(
629 entry
->sfe_cookie
, so
, nam
);
632 * Take the socket filter lock again and
635 lck_rw_lock_shared(sock_filter_lock
);
636 sflt_entry_release(entry
);
639 lck_rw_unlock_shared(sock_filter_lock
);
648 __private_extern__
int
649 sflt_listen(struct socket
*so
)
651 if (so
->so_filt
== NULL
)
654 struct socket_filter_entry
*entry
;
658 lck_rw_lock_shared(sock_filter_lock
);
659 for (entry
= so
->so_filt
; entry
&& error
== 0;
660 entry
= entry
->sfe_next_onsocket
) {
661 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
662 entry
->sfe_filter
->sf_filter
.sf_listen
) {
664 * Retain the filter entry and release
665 * the socket filter lock
667 sflt_entry_retain(entry
);
668 lck_rw_unlock_shared(sock_filter_lock
);
670 /* If the socket isn't already unlocked, unlock it */
672 socket_unlock(so
, 0);
676 /* Call the filter */
677 error
= entry
->sfe_filter
->sf_filter
.sf_listen(
678 entry
->sfe_cookie
, so
);
681 * Take the socket filter lock again
682 * and release the entry
684 lck_rw_lock_shared(sock_filter_lock
);
685 sflt_entry_release(entry
);
688 lck_rw_unlock_shared(sock_filter_lock
);
697 __private_extern__
int
698 sflt_accept(struct socket
*head
, struct socket
*so
,
699 const struct sockaddr
*local
, const struct sockaddr
*remote
)
701 if (so
->so_filt
== NULL
)
704 struct socket_filter_entry
*entry
;
708 lck_rw_lock_shared(sock_filter_lock
);
709 for (entry
= so
->so_filt
; entry
&& error
== 0;
710 entry
= entry
->sfe_next_onsocket
) {
711 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
712 entry
->sfe_filter
->sf_filter
.sf_accept
) {
714 * Retain the filter entry and
715 * release the socket filter lock
717 sflt_entry_retain(entry
);
718 lck_rw_unlock_shared(sock_filter_lock
);
720 /* If the socket isn't already unlocked, unlock it */
722 socket_unlock(so
, 0);
726 /* Call the filter */
727 error
= entry
->sfe_filter
->sf_filter
.sf_accept(
728 entry
->sfe_cookie
, head
, so
, local
, remote
);
731 * Take the socket filter lock again
732 * and release the entry
734 lck_rw_lock_shared(sock_filter_lock
);
735 sflt_entry_release(entry
);
738 lck_rw_unlock_shared(sock_filter_lock
);
747 __private_extern__
int
748 sflt_getsockname(struct socket
*so
, struct sockaddr
**local
)
750 if (so
->so_filt
== NULL
)
753 struct socket_filter_entry
*entry
;
757 lck_rw_lock_shared(sock_filter_lock
);
758 for (entry
= so
->so_filt
; entry
&& error
== 0;
759 entry
= entry
->sfe_next_onsocket
) {
760 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
761 entry
->sfe_filter
->sf_filter
.sf_getsockname
) {
763 * Retain the filter entry and
764 * release the socket filter lock
766 sflt_entry_retain(entry
);
767 lck_rw_unlock_shared(sock_filter_lock
);
769 /* If the socket isn't already unlocked, unlock it */
771 socket_unlock(so
, 0);
775 /* Call the filter */
776 error
= entry
->sfe_filter
->sf_filter
.sf_getsockname(
777 entry
->sfe_cookie
, so
, local
);
780 * Take the socket filter lock again
781 * and release the entry
783 lck_rw_lock_shared(sock_filter_lock
);
784 sflt_entry_release(entry
);
787 lck_rw_unlock_shared(sock_filter_lock
);
796 __private_extern__
int
797 sflt_getpeername(struct socket
*so
, struct sockaddr
**remote
)
799 if (so
->so_filt
== NULL
)
802 struct socket_filter_entry
*entry
;
806 lck_rw_lock_shared(sock_filter_lock
);
807 for (entry
= so
->so_filt
; entry
&& error
== 0;
808 entry
= entry
->sfe_next_onsocket
) {
809 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
810 entry
->sfe_filter
->sf_filter
.sf_getpeername
) {
812 * Retain the filter entry and release
813 * the socket filter lock
815 sflt_entry_retain(entry
);
816 lck_rw_unlock_shared(sock_filter_lock
);
818 /* If the socket isn't already unlocked, unlock it */
820 socket_unlock(so
, 0);
824 /* Call the filter */
825 error
= entry
->sfe_filter
->sf_filter
.sf_getpeername(
826 entry
->sfe_cookie
, so
, remote
);
829 * Take the socket filter lock again
830 * and release the entry
832 lck_rw_lock_shared(sock_filter_lock
);
833 sflt_entry_release(entry
);
836 lck_rw_unlock_shared(sock_filter_lock
);
845 __private_extern__
int
846 sflt_connectin(struct socket
*so
, const struct sockaddr
*remote
)
848 if (so
->so_filt
== NULL
)
851 struct socket_filter_entry
*entry
;
855 lck_rw_lock_shared(sock_filter_lock
);
856 for (entry
= so
->so_filt
; entry
&& error
== 0;
857 entry
= entry
->sfe_next_onsocket
) {
858 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
859 entry
->sfe_filter
->sf_filter
.sf_connect_in
) {
861 * Retain the filter entry and release
862 * the socket filter lock
864 sflt_entry_retain(entry
);
865 lck_rw_unlock_shared(sock_filter_lock
);
867 /* If the socket isn't already unlocked, unlock it */
869 socket_unlock(so
, 0);
873 /* Call the filter */
874 error
= entry
->sfe_filter
->sf_filter
.sf_connect_in(
875 entry
->sfe_cookie
, so
, remote
);
878 * Take the socket filter lock again
879 * and release the entry
881 lck_rw_lock_shared(sock_filter_lock
);
882 sflt_entry_release(entry
);
885 lck_rw_unlock_shared(sock_filter_lock
);
894 __private_extern__
int
895 sflt_connectout(struct socket
*so
, const struct sockaddr
*nam
)
897 if (so
->so_filt
== NULL
)
900 struct socket_filter_entry
*entry
;
904 lck_rw_lock_shared(sock_filter_lock
);
905 for (entry
= so
->so_filt
; entry
&& error
== 0;
906 entry
= entry
->sfe_next_onsocket
) {
907 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
908 entry
->sfe_filter
->sf_filter
.sf_connect_out
) {
910 * Retain the filter entry and release
911 * the socket filter lock
913 sflt_entry_retain(entry
);
914 lck_rw_unlock_shared(sock_filter_lock
);
916 /* If the socket isn't already unlocked, unlock it */
918 socket_unlock(so
, 0);
922 /* Call the filter */
923 error
= entry
->sfe_filter
->sf_filter
.sf_connect_out(
924 entry
->sfe_cookie
, so
, nam
);
927 * Take the socket filter lock again
928 * and release the entry
930 lck_rw_lock_shared(sock_filter_lock
);
931 sflt_entry_release(entry
);
934 lck_rw_unlock_shared(sock_filter_lock
);
943 __private_extern__
int
944 sflt_connectxout(struct socket
*so
, struct sockaddr_list
**dst_sl0
)
946 char buf
[SOCK_MAXADDRLEN
];
947 struct sockaddr_list
*dst_sl
;
948 struct sockaddr_entry
*se
, *tse
;
952 if (so
->so_filt
== NULL
)
955 /* make a copy as sflt_connectout() releases socket lock */
956 dst_sl
= sockaddrlist_dup(*dst_sl0
, M_WAITOK
);
961 * Hmm; we don't yet have a connectx socket filter callback,
962 * so the closest thing to do is to probably call sflt_connectout()
963 * as many times as there are addresses in the list, and bail
964 * as soon as we get an error.
966 TAILQ_FOREACH_SAFE(se
, &dst_sl
->sl_head
, se_link
, tse
) {
967 int sa_len
= se
->se_addr
->sa_len
;
969 /* remember the original address */
970 bzero(buf
, sizeof (buf
));
971 bcopy(se
->se_addr
, buf
, sa_len
);
973 VERIFY(se
->se_addr
!= NULL
);
974 error
= sflt_connectout(so
, se
->se_addr
);
978 /* see if the address was modified */
979 if (bcmp(se
->se_addr
, buf
, sa_len
) != 0)
983 if (error
!= 0 || !modified
) {
984 /* leave the original as is */
985 sockaddrlist_free(dst_sl
);
988 * At least one address was modified and there were no errors;
989 * ditch the original and return the modified list.
991 sockaddrlist_free(*dst_sl0
);
998 __private_extern__
int
999 sflt_setsockopt(struct socket
*so
, struct sockopt
*sopt
)
1001 if (so
->so_filt
== NULL
)
1004 struct socket_filter_entry
*entry
;
1008 lck_rw_lock_shared(sock_filter_lock
);
1009 for (entry
= so
->so_filt
; entry
&& error
== 0;
1010 entry
= entry
->sfe_next_onsocket
) {
1011 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
1012 entry
->sfe_filter
->sf_filter
.sf_setoption
) {
1014 * Retain the filter entry and release
1015 * the socket filter lock
1017 sflt_entry_retain(entry
);
1018 lck_rw_unlock_shared(sock_filter_lock
);
1020 /* If the socket isn't already unlocked, unlock it */
1021 if (unlocked
== 0) {
1022 socket_unlock(so
, 0);
1026 /* Call the filter */
1027 error
= entry
->sfe_filter
->sf_filter
.sf_setoption(
1028 entry
->sfe_cookie
, so
, sopt
);
1031 * Take the socket filter lock again
1032 * and release the entry
1034 lck_rw_lock_shared(sock_filter_lock
);
1035 sflt_entry_release(entry
);
1038 lck_rw_unlock_shared(sock_filter_lock
);
1047 __private_extern__
int
1048 sflt_getsockopt(struct socket
*so
, struct sockopt
*sopt
)
1050 if (so
->so_filt
== NULL
)
1053 struct socket_filter_entry
*entry
;
1057 lck_rw_lock_shared(sock_filter_lock
);
1058 for (entry
= so
->so_filt
; entry
&& error
== 0;
1059 entry
= entry
->sfe_next_onsocket
) {
1060 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
1061 entry
->sfe_filter
->sf_filter
.sf_getoption
) {
1063 * Retain the filter entry and release
1064 * the socket filter lock
1066 sflt_entry_retain(entry
);
1067 lck_rw_unlock_shared(sock_filter_lock
);
1069 /* If the socket isn't already unlocked, unlock it */
1070 if (unlocked
== 0) {
1071 socket_unlock(so
, 0);
1075 /* Call the filter */
1076 error
= entry
->sfe_filter
->sf_filter
.sf_getoption(
1077 entry
->sfe_cookie
, so
, sopt
);
1080 * Take the socket filter lock again
1081 * and release the entry
1083 lck_rw_lock_shared(sock_filter_lock
);
1084 sflt_entry_release(entry
);
1087 lck_rw_unlock_shared(sock_filter_lock
);
1096 __private_extern__
int
1097 sflt_data_out(struct socket
*so
, const struct sockaddr
*to
, mbuf_t
*data
,
1098 mbuf_t
*control
, sflt_data_flag_t flags
)
1100 if (so
->so_filt
== NULL
)
1103 struct socket_filter_entry
*entry
;
1105 int setsendthread
= 0;
1108 lck_rw_lock_shared(sock_filter_lock
);
1109 for (entry
= so
->so_filt
; entry
&& error
== 0;
1110 entry
= entry
->sfe_next_onsocket
) {
1111 /* skip if this is a subflow socket */
1112 if (so
->so_flags
& SOF_MP_SUBFLOW
)
1114 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
1115 entry
->sfe_filter
->sf_filter
.sf_data_out
) {
1117 * Retain the filter entry and
1118 * release the socket filter lock
1120 sflt_entry_retain(entry
);
1121 lck_rw_unlock_shared(sock_filter_lock
);
1123 /* If the socket isn't already unlocked, unlock it */
1124 if (unlocked
== 0) {
1125 if (so
->so_send_filt_thread
== NULL
) {
1127 so
->so_send_filt_thread
=
1130 socket_unlock(so
, 0);
1134 /* Call the filter */
1135 error
= entry
->sfe_filter
->sf_filter
.sf_data_out(
1136 entry
->sfe_cookie
, so
, to
, data
, control
, flags
);
1139 * Take the socket filter lock again
1140 * and release the entry
1142 lck_rw_lock_shared(sock_filter_lock
);
1143 sflt_entry_release(entry
);
1146 lck_rw_unlock_shared(sock_filter_lock
);
1151 so
->so_send_filt_thread
= NULL
;
1157 __private_extern__
int
1158 sflt_data_in(struct socket
*so
, const struct sockaddr
*from
, mbuf_t
*data
,
1159 mbuf_t
*control
, sflt_data_flag_t flags
)
1161 if (so
->so_filt
== NULL
)
1164 struct socket_filter_entry
*entry
;
1168 lck_rw_lock_shared(sock_filter_lock
);
1170 for (entry
= so
->so_filt
; entry
&& (error
== 0);
1171 entry
= entry
->sfe_next_onsocket
) {
1172 /* skip if this is a subflow socket */
1173 if (so
->so_flags
& SOF_MP_SUBFLOW
)
1175 if ((entry
->sfe_flags
& SFEF_ATTACHED
) &&
1176 entry
->sfe_filter
->sf_filter
.sf_data_in
) {
1178 * Retain the filter entry and
1179 * release the socket filter lock
1181 sflt_entry_retain(entry
);
1182 lck_rw_unlock_shared(sock_filter_lock
);
1184 /* If the socket isn't already unlocked, unlock it */
1185 if (unlocked
== 0) {
1187 socket_unlock(so
, 0);
1190 /* Call the filter */
1191 error
= entry
->sfe_filter
->sf_filter
.sf_data_in(
1192 entry
->sfe_cookie
, so
, from
, data
, control
, flags
);
1195 * Take the socket filter lock again
1196 * and release the entry
1198 lck_rw_lock_shared(sock_filter_lock
);
1199 sflt_entry_release(entry
);
1202 lck_rw_unlock_shared(sock_filter_lock
);
1211 #pragma mark -- KPI --
1214 sflt_attach(socket_t socket
, sflt_handle handle
)
1216 socket_lock(socket
, 1);
1217 errno_t result
= sflt_attach_internal(socket
, handle
);
1218 socket_unlock(socket
, 1);
1223 sflt_detach(socket_t socket
, sflt_handle handle
)
1225 struct socket_filter_entry
*entry
;
1228 if (socket
== NULL
|| handle
== 0)
1231 lck_rw_lock_exclusive(sock_filter_lock
);
1232 for (entry
= socket
->so_filt
; entry
; entry
= entry
->sfe_next_onsocket
) {
1233 if (entry
->sfe_filter
->sf_filter
.sf_handle
== handle
&&
1234 (entry
->sfe_flags
& SFEF_ATTACHED
) != 0) {
1239 if (entry
!= NULL
) {
1240 sflt_detach_locked(entry
);
1242 lck_rw_unlock_exclusive(sock_filter_lock
);
1248 struct solist
*next
;
1253 sflt_register(const struct sflt_filter
*filter
, int domain
, int type
,
1256 struct socket_filter
*sock_filt
= NULL
;
1257 struct socket_filter
*match
= NULL
;
1259 struct protosw
*pr
= pffindproto(domain
, protocol
, type
);
1263 struct solist
*solisthead
= NULL
, *solist
= NULL
;
1268 if (filter
->sf_attach
== NULL
|| filter
->sf_detach
== NULL
||
1269 filter
->sf_handle
== 0 || filter
->sf_name
== NULL
)
1272 /* Allocate the socket filter */
1273 MALLOC(sock_filt
, struct socket_filter
*, sizeof (*sock_filt
),
1274 M_IFADDR
, M_WAITOK
);
1275 if (sock_filt
== NULL
) {
1279 bzero(sock_filt
, sizeof (*sock_filt
));
1281 /* Legacy sflt_filter length; current structure minus extended */
1282 len
= sizeof (*filter
) - sizeof (struct sflt_filter_ext
);
1284 * Include extended fields if filter defines SFLT_EXTENDED.
1285 * We've zeroed out our internal sflt_filter placeholder,
1286 * so any unused portion would have been taken care of.
1288 if (filter
->sf_flags
& SFLT_EXTENDED
) {
1289 unsigned int ext_len
= filter
->sf_len
;
1291 if (ext_len
> sizeof (struct sflt_filter_ext
))
1292 ext_len
= sizeof (struct sflt_filter_ext
);
1296 bcopy(filter
, &sock_filt
->sf_filter
, len
);
1298 lck_rw_lock_exclusive(sock_filter_lock
);
1299 /* Look for an existing entry */
1300 TAILQ_FOREACH(match
, &sock_filter_head
, sf_global_next
) {
1301 if (match
->sf_filter
.sf_handle
==
1302 sock_filt
->sf_filter
.sf_handle
) {
1307 /* Add the entry only if there was no existing entry */
1308 if (match
== NULL
) {
1309 TAILQ_INSERT_TAIL(&sock_filter_head
, sock_filt
, sf_global_next
);
1310 if ((sock_filt
->sf_filter
.sf_flags
& SFLT_GLOBAL
) != 0) {
1311 TAILQ_INSERT_TAIL(&pr
->pr_filter_head
, sock_filt
,
1313 sock_filt
->sf_proto
= pr
;
1315 sflt_retain_locked(sock_filt
);
1317 lck_rw_unlock_exclusive(sock_filter_lock
);
1319 if (match
!= NULL
) {
1320 FREE(sock_filt
, M_IFADDR
);
1324 if (!(filter
->sf_flags
& SFLT_EXTENDED_REGISTRY
))
1328 * Setup the filter on the TCP and UDP sockets already created.
1330 #define SOLIST_ADD(_so) do { \
1331 solist->next = solisthead; \
1332 sock_retain((_so)); \
1333 solist->so = (_so); \
1334 solisthead = solist; \
1336 if (protocol
== IPPROTO_TCP
) {
1337 lck_rw_lock_shared(tcbinfo
.ipi_lock
);
1338 LIST_FOREACH(inp
, tcbinfo
.ipi_listhead
, inp_list
) {
1339 so
= inp
->inp_socket
;
1340 if (so
== NULL
|| (so
->so_state
& SS_DEFUNCT
) ||
1341 (!(so
->so_flags
& SOF_MP_SUBFLOW
) &&
1342 (so
->so_state
& SS_NOFDREF
)) ||
1343 !SOCK_CHECK_DOM(so
, domain
) ||
1344 !SOCK_CHECK_TYPE(so
, type
))
1346 MALLOC(solist
, struct solist
*, sizeof (*solist
),
1347 M_IFADDR
, M_NOWAIT
);
1352 lck_rw_done(tcbinfo
.ipi_lock
);
1353 } else if (protocol
== IPPROTO_UDP
) {
1354 lck_rw_lock_shared(udbinfo
.ipi_lock
);
1355 LIST_FOREACH(inp
, udbinfo
.ipi_listhead
, inp_list
) {
1356 so
= inp
->inp_socket
;
1357 if (so
== NULL
|| (so
->so_state
& SS_DEFUNCT
) ||
1358 (!(so
->so_flags
& SOF_MP_SUBFLOW
) &&
1359 (so
->so_state
& SS_NOFDREF
)) ||
1360 !SOCK_CHECK_DOM(so
, domain
) ||
1361 !SOCK_CHECK_TYPE(so
, type
))
1363 MALLOC(solist
, struct solist
*, sizeof (*solist
),
1364 M_IFADDR
, M_NOWAIT
);
1369 lck_rw_done(udbinfo
.ipi_lock
);
1371 /* XXX it's possible to walk the raw socket list as well */
1374 while (solisthead
) {
1375 sflt_handle handle
= filter
->sf_handle
;
1377 so
= solisthead
->so
;
1380 if (so
->so_state
& SS_ISCONNECTING
)
1381 sflt_notify_after_register(so
, sock_evt_connecting
,
1383 else if (so
->so_state
& SS_ISCONNECTED
)
1384 sflt_notify_after_register(so
, sock_evt_connected
,
1386 else if ((so
->so_state
&
1387 (SS_ISDISCONNECTING
|SS_CANTRCVMORE
|SS_CANTSENDMORE
)) ==
1388 (SS_ISDISCONNECTING
|SS_CANTRCVMORE
|SS_CANTSENDMORE
))
1389 sflt_notify_after_register(so
, sock_evt_disconnecting
,
1391 else if ((so
->so_state
&
1392 (SS_CANTRCVMORE
|SS_CANTSENDMORE
|SS_ISDISCONNECTED
)) ==
1393 (SS_CANTRCVMORE
|SS_CANTSENDMORE
|SS_ISDISCONNECTED
))
1394 sflt_notify_after_register(so
, sock_evt_disconnected
,
1396 else if (so
->so_state
& SS_CANTSENDMORE
)
1397 sflt_notify_after_register(so
, sock_evt_cantsendmore
,
1399 else if (so
->so_state
& SS_CANTRCVMORE
)
1400 sflt_notify_after_register(so
, sock_evt_cantrecvmore
,
1402 /* XXX no easy way to post the sock_evt_closing event */
1404 solist
= solisthead
;
1405 solisthead
= solisthead
->next
;
1406 FREE(solist
, M_IFADDR
);
1413 sflt_unregister(sflt_handle handle
)
1415 struct socket_filter
*filter
;
1416 lck_rw_lock_exclusive(sock_filter_lock
);
1418 /* Find the entry by the handle */
1419 TAILQ_FOREACH(filter
, &sock_filter_head
, sf_global_next
) {
1420 if (filter
->sf_filter
.sf_handle
== handle
)
1425 /* Remove it from the global list */
1426 TAILQ_REMOVE(&sock_filter_head
, filter
, sf_global_next
);
1428 /* Remove it from the protosw list */
1429 if ((filter
->sf_filter
.sf_flags
& SFLT_GLOBAL
) != 0) {
1430 TAILQ_REMOVE(&filter
->sf_proto
->pr_filter_head
,
1431 filter
, sf_protosw_next
);
1434 /* Detach from any sockets */
1435 struct socket_filter_entry
*entry
= NULL
;
1437 for (entry
= filter
->sf_entry_head
; entry
;
1438 entry
= entry
->sfe_next_onfilter
) {
1439 sflt_detach_locked(entry
);
1442 /* Release the filter */
1443 sflt_release_locked(filter
);
1446 lck_rw_unlock_exclusive(sock_filter_lock
);
1455 sock_inject_data_in(socket_t so
, const struct sockaddr
*from
, mbuf_t data
,
1456 mbuf_t control
, sflt_data_flag_t flags
)
1460 if (so
== NULL
|| data
== NULL
)
1463 if (flags
& sock_data_filt_flag_oob
) {
1469 /* reject if this is a subflow socket */
1470 if (so
->so_flags
& SOF_MP_SUBFLOW
) {
1476 if (sbappendaddr(&so
->so_rcv
,
1477 (struct sockaddr
*)(uintptr_t)from
, data
, control
, NULL
))
1483 if (sbappendcontrol(&so
->so_rcv
, data
, control
, NULL
))
1488 if (flags
& sock_data_filt_flag_record
) {
1489 if (control
|| from
) {
1493 if (sbappendrecord(&so
->so_rcv
, (struct mbuf
*)data
))
1498 if (sbappend(&so
->so_rcv
, data
))
1501 socket_unlock(so
, 1);
1506 sock_inject_data_out(socket_t so
, const struct sockaddr
*to
, mbuf_t data
,
1507 mbuf_t control
, sflt_data_flag_t flags
)
1509 int sosendflags
= 0;
1511 /* reject if this is a subflow socket */
1512 if (so
->so_flags
& SOF_MP_SUBFLOW
)
1515 if (flags
& sock_data_filt_flag_oob
)
1516 sosendflags
= MSG_OOB
;
1517 return (sosend(so
, (struct sockaddr
*)(uintptr_t)to
, NULL
,
1518 data
, control
, sosendflags
));
1522 sockopt_direction(sockopt_t sopt
)
1524 return ((sopt
->sopt_dir
== SOPT_GET
) ? sockopt_get
: sockopt_set
);
1528 sockopt_level(sockopt_t sopt
)
1530 return (sopt
->sopt_level
);
1534 sockopt_name(sockopt_t sopt
)
1536 return (sopt
->sopt_name
);
1540 sockopt_valsize(sockopt_t sopt
)
1542 return (sopt
->sopt_valsize
);
1546 sockopt_copyin(sockopt_t sopt
, void *data
, size_t len
)
1548 return (sooptcopyin(sopt
, data
, len
, len
));
1552 sockopt_copyout(sockopt_t sopt
, void *data
, size_t len
)
1554 return (sooptcopyout(sopt
, data
, len
));