]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kpi_socketfilter.c
xnu-2422.1.72.tar.gz
[apple/xnu.git] / bsd / kern / kpi_socketfilter.c
index f456d62465351787213c5e5a46d2fe4c03327773..1b55a8053c9b315e50571bef689aea732456ecc5 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2003-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
@@ -61,32 +61,32 @@ struct socket_filter_entry {
        struct socket_filter_entry      *sfe_next_onsocket;
        struct socket_filter_entry      *sfe_next_onfilter;
        struct socket_filter_entry      *sfe_next_oncleanup;
-       
+
        struct socket_filter            *sfe_filter;
-       struct socket                           *sfe_socket;
-       void                                            *sfe_cookie;
-       
-       uint32_t                                        sfe_flags;
-       int32_t                                         sfe_refcount;
+       struct socket                   *sfe_socket;
+       void                            *sfe_cookie;
+
+       uint32_t                        sfe_flags;
+       int32_t                         sfe_refcount;
 };
 
 struct socket_filter {
-       TAILQ_ENTRY(socket_filter)      sf_protosw_next;        
+       TAILQ_ENTRY(socket_filter)      sf_protosw_next;
        TAILQ_ENTRY(socket_filter)      sf_global_next;
        struct socket_filter_entry      *sf_entry_head;
-       
-       struct protosw                          *sf_proto;
-       struct sflt_filter                      sf_filter;
-       u_int32_t                                       sf_refcount;
+
+       struct protosw                  *sf_proto;
+       struct sflt_filter              sf_filter;
+       u_int32_t                       sf_refcount;
 };
 
 TAILQ_HEAD(socket_filter_list, socket_filter);
 
 static struct socket_filter_list       sock_filter_head;
-static lck_rw_t                                                *sock_filter_lock = NULL;
-static lck_mtx_t                                       *sock_filter_cleanup_lock = NULL;
+static lck_rw_t                                *sock_filter_lock = NULL;
+static lck_mtx_t                       *sock_filter_cleanup_lock = NULL;
 static struct socket_filter_entry      *sock_filter_cleanup_entries = NULL;
-static thread_t                                                sock_filter_cleanup_thread = NULL;
+static thread_t                                sock_filter_cleanup_thread = NULL;
 
 static void sflt_cleanup_thread(void *, wait_result_t);
 static void sflt_detach_locked(struct socket_filter_entry *entry);
@@ -96,12 +96,12 @@ static void sflt_detach_locked(struct socket_filter_entry *entry);
 __private_extern__ void
 sflt_init(void)
 {
-       lck_grp_attr_t  *grp_attrib = 0;
-       lck_attr_t              *lck_attrib = 0;
-       lck_grp_t               *lck_group = 0;
-       
+       lck_grp_attr_t  *grp_attrib = NULL;
+       lck_attr_t      *lck_attrib = NULL;
+       lck_grp_t       *lck_group = NULL;
+
        TAILQ_INIT(&sock_filter_head);
-       
+
        /* Allocate a rw lock */
        grp_attrib = lck_grp_attr_alloc_init();
        lck_group = lck_grp_alloc_init("socket filter lock", grp_attrib);
@@ -114,251 +114,264 @@ sflt_init(void)
 }
 
 static void
-sflt_retain_locked(
-       struct socket_filter    *filter)
+sflt_retain_locked(struct socket_filter        *filter)
 {
        filter->sf_refcount++;
 }
 
 static void
-sflt_release_locked(
-       struct socket_filter    *filter)
+sflt_release_locked(struct socket_filter *filter)
 {
        filter->sf_refcount--;
-       if (filter->sf_refcount == 0)
-       {
-               // Call the unregistered function
+       if (filter->sf_refcount == 0) {
+               /* Call the unregistered function */
                if (filter->sf_filter.sf_unregistered) {
                        lck_rw_unlock_exclusive(sock_filter_lock);
-                       filter->sf_filter.sf_unregistered(filter->sf_filter.sf_handle);
+                       filter->sf_filter.sf_unregistered(
+                           filter->sf_filter.sf_handle);
                        lck_rw_lock_exclusive(sock_filter_lock);
                }
-               
-               // Free the entry
+
+               /* Free the entry */
                FREE(filter, M_IFADDR);
        }
 }
 
 static void
-sflt_entry_retain(
-       struct socket_filter_entry *entry)
+sflt_entry_retain(struct socket_filter_entry *entry)
 {
-       if (OSIncrementAtomic(&entry->sfe_refcount) <= 0)
+       if (OSIncrementAtomic(&entry->sfe_refcount) <= 0) {
                panic("sflt_entry_retain - sfe_refcount <= 0\n");
+               /* NOTREACHED */
+       }
 }
 
 static void
-sflt_entry_release(
-       struct socket_filter_entry *entry)
+sflt_entry_release(struct socket_filter_entry *entry)
 {
        SInt32 old = OSDecrementAtomic(&entry->sfe_refcount);
        if (old == 1) {
-               // That was the last reference
-               
-               // Take the cleanup lock
+               /* That was the last reference */
+
+               /* Take the cleanup lock */
                lck_mtx_lock(sock_filter_cleanup_lock);
-               
-               // Put this item on the cleanup list
+
+               /* Put this item on the cleanup list */
                entry->sfe_next_oncleanup = sock_filter_cleanup_entries;
                sock_filter_cleanup_entries = entry;
-               
-               // If the item is the first item in the list
+
+               /* If the item is the first item in the list */
                if (entry->sfe_next_oncleanup == NULL) {
                        if (sock_filter_cleanup_thread == NULL) {
-                               // Create a thread
-                               kernel_thread_start(sflt_cleanup_thread, NULL, &sock_filter_cleanup_thread);
+                               /* Create a thread */
+                               kernel_thread_start(sflt_cleanup_thread,
+                                   NULL, &sock_filter_cleanup_thread);
                        } else {
-                               // Wakeup the thread
+                               /* Wakeup the thread */
                                wakeup(&sock_filter_cleanup_entries);
                        }
                }
-               
-               // Drop the cleanup lock
+
+               /* Drop the cleanup lock */
                lck_mtx_unlock(sock_filter_cleanup_lock);
-       }
-       else if (old <= 0)
-       {
-               panic("sflt_entry_release - sfe_refcount (%d) <= 0\n", (int)old);
+       } else if (old <= 0) {
+               panic("sflt_entry_release - sfe_refcount (%d) <= 0\n",
+                   (int)old);
+               /* NOTREACHED */
        }
 }
 
 static void
-sflt_cleanup_thread(
-       __unused void * blah,
-       __unused wait_result_t blah2)
+sflt_cleanup_thread(void *blah, wait_result_t blah2)
 {
+#pragma unused(blah, blah2)
        while (1) {
                lck_mtx_lock(sock_filter_cleanup_lock);
                while (sock_filter_cleanup_entries == NULL) {
-                       // Sleep until we've got something better to do
-                       msleep(&sock_filter_cleanup_entries, sock_filter_cleanup_lock, PWAIT, "sflt_cleanup", NULL);
+                       /* Sleep until we've got something better to do */
+                       msleep(&sock_filter_cleanup_entries,
+                           sock_filter_cleanup_lock, PWAIT,
+                           "sflt_cleanup", NULL);
                }
-               
-               // Pull the current list of dead items
-               struct socket_filter_entry      *dead = sock_filter_cleanup_entries;
+
+               /* Pull the current list of dead items */
+               struct socket_filter_entry *dead = sock_filter_cleanup_entries;
                sock_filter_cleanup_entries = NULL;
-               
-               // Drop the lock
+
+               /* Drop the lock */
                lck_mtx_unlock(sock_filter_cleanup_lock);
-               
-               // Take the socket filter lock
+
+               /* Take the socket filter lock */
                lck_rw_lock_exclusive(sock_filter_lock);
-               
-               // Cleanup every dead item
+
+               /* Cleanup every dead item */
                struct socket_filter_entry      *entry;
                for (entry = dead; entry; entry = dead) {
                        struct socket_filter_entry      **nextpp;
-                       
+
                        dead = entry->sfe_next_oncleanup;
-                       
-                       // Call the detach function if necessary - drop the lock
+
+                       /* Call detach function if necessary - drop the lock */
                        if ((entry->sfe_flags & SFEF_NODETACH) == 0 &&
-                               entry->sfe_filter->sf_filter.sf_detach) {
+                           entry->sfe_filter->sf_filter.sf_detach) {
                                entry->sfe_flags |= SFEF_NODETACH;
                                lck_rw_unlock_exclusive(sock_filter_lock);
-                               
-                               // Warning - passing a potentially dead socket may be bad
-                               entry->sfe_filter->sf_filter.
-                                       sf_detach(entry->sfe_cookie, entry->sfe_socket);
-                               
+
+                               /*
+                                * Warning - passing a potentially
+                                * dead socket may be bad
+                                */
+                               entry->sfe_filter->sf_filter. sf_detach(
+                                   entry->sfe_cookie, entry->sfe_socket);
+
                                lck_rw_lock_exclusive(sock_filter_lock);
                        }
-                       
-                       // Pull entry off the socket list -- if the socket still exists
+
+                       /*
+                        * Pull entry off the socket list --
+                        * if the socket still exists
+                        */
                        if ((entry->sfe_flags & SFEF_NOSOCKET) == 0) {
-                               for (nextpp = &entry->sfe_socket->so_filt; *nextpp;
-                                        nextpp = &(*nextpp)->sfe_next_onsocket) {
+                               for (nextpp = &entry->sfe_socket->so_filt;
+                                   *nextpp;
+                                   nextpp = &(*nextpp)->sfe_next_onsocket) {
                                        if (*nextpp == entry) {
-                                               *nextpp = entry->sfe_next_onsocket;
+                                               *nextpp =
+                                                   entry->sfe_next_onsocket;
                                                break;
                                        }
                                }
                        }
-                       
-                       // Pull entry off the filter list
-                       for (nextpp = &entry->sfe_filter->sf_entry_head; *nextpp;
-                                nextpp = &(*nextpp)->sfe_next_onfilter) {
+
+                       /* Pull entry off the filter list */
+                       for (nextpp = &entry->sfe_filter->sf_entry_head;
+                           *nextpp; nextpp = &(*nextpp)->sfe_next_onfilter) {
                                if (*nextpp == entry) {
                                        *nextpp = entry->sfe_next_onfilter;
                                        break;
                                }
                        }
-                       
-                       // Release the filter -- may drop lock, but that's okay
+
+                       /*
+                        * Release the filter -- may drop lock, but that's okay
+                        */
                        sflt_release_locked(entry->sfe_filter);
                        entry->sfe_socket = NULL;
                        entry->sfe_filter = NULL;
                        FREE(entry, M_IFADDR);
                }
-               
-               // Drop the socket filter lock
+
+               /* Drop the socket filter lock */
                lck_rw_unlock_exclusive(sock_filter_lock);
        }
-       // Not reached
+       /* NOTREACHED */
 }
 
 static int
-sflt_attach_locked(
-       struct socket                   *so,
-       struct socket_filter    *filter,
-       int                                             socklocked)
+sflt_attach_locked(struct socket *so, struct socket_filter *filter,
+    int socklocked)
 {
        int error = 0;
        struct socket_filter_entry *entry = NULL;
-       
+
        if (filter == NULL)
-               return ENOENT;
+               return (ENOENT);
 
-       for (entry = so->so_filt; entry; entry = entry->sfe_next_onfilter) 
+       for (entry = so->so_filt; entry; entry = entry->sfe_next_onfilter) {
                if (entry->sfe_filter->sf_filter.sf_handle ==
                    filter->sf_filter.sf_handle)
-                       return EEXIST;
-
+                       return (EEXIST);
+       }
        /* allocate the socket filter entry */
-       MALLOC(entry, struct socket_filter_entry *, sizeof(*entry), M_IFADDR,
+       MALLOC(entry, struct socket_filter_entry *, sizeof (*entry), M_IFADDR,
            M_WAITOK);
        if (entry == NULL)
-               return ENOMEM;
-       
+               return (ENOMEM);
+
        /* Initialize the socket filter entry */
        entry->sfe_cookie = NULL;
        entry->sfe_flags = SFEF_ATTACHED;
-       entry->sfe_refcount = 1; // corresponds to SFEF_ATTACHED flag set
-       
+       entry->sfe_refcount = 1; /* corresponds to SFEF_ATTACHED flag set */
+
        /* Put the entry in the filter list */
        sflt_retain_locked(filter);
        entry->sfe_filter = filter;
        entry->sfe_next_onfilter = filter->sf_entry_head;
        filter->sf_entry_head = entry;
-       
+
        /* Put the entry on the socket filter list */
        entry->sfe_socket = so;
        entry->sfe_next_onsocket = so->so_filt;
        so->so_filt = entry;
 
        if (entry->sfe_filter->sf_filter.sf_attach) {
-               // Retain the entry while we call attach
+               /* Retain the entry while we call attach */
                sflt_entry_retain(entry);
-               
-               // Release the filter lock -- callers must be aware we will do this
+
+               /*
+                * Release the filter lock --
+                * callers must be aware we will do this
+                */
                lck_rw_unlock_exclusive(sock_filter_lock);
-               
-               // Unlock the socket
+
+               /* Unlock the socket */
                if (socklocked)
                        socket_unlock(so, 0);
-               
-               // It's finally safe to call the filter function
-               error = entry->sfe_filter->sf_filter.sf_attach(&entry->sfe_cookie, so);
-               
-               // Lock the socket again
+
+               /* It's finally safe to call the filter function */
+               error = entry->sfe_filter->sf_filter.sf_attach(
+                   &entry->sfe_cookie, so);
+
+               /* Lock the socket again */
                if (socklocked)
                        socket_lock(so, 0);
-               
-               // Lock the filters again
+
+               /* Lock the filters again */
                lck_rw_lock_exclusive(sock_filter_lock);
-               
-               // If the attach function returns an error, this filter must be detached
+
+               /*
+                * If the attach function returns an error,
+                * this filter must be detached
+                */
                if (error) {
-                       entry->sfe_flags |= SFEF_NODETACH; // don't call sf_detach
+                       /* don't call sf_detach */
+                       entry->sfe_flags |= SFEF_NODETACH;
                        sflt_detach_locked(entry);
                }
-               
-               // Release the retain we held through the attach call
+
+               /* Release the retain we held through the attach call */
                sflt_entry_release(entry);
        }
-       
-       return error;
+
+       return (error);
 }
 
 errno_t
-sflt_attach_internal(
-       socket_t        socket,
-       sflt_handle     handle)
+sflt_attach_internal(socket_t socket, sflt_handle handle)
 {
        if (socket == NULL || handle == 0)
-               return EINVAL;
-       
+               return (EINVAL);
+
        int result = EINVAL;
-       
+
        lck_rw_lock_exclusive(sock_filter_lock);
-       
+
        struct socket_filter *filter = NULL;
        TAILQ_FOREACH(filter, &sock_filter_head, sf_global_next) {
                if (filter->sf_filter.sf_handle == handle) break;
        }
-       
+
        if (filter) {
                result = sflt_attach_locked(socket, filter, 1);
        }
-       
+
        lck_rw_unlock_exclusive(sock_filter_lock);
-       
-       return result;
+
+       return (result);
 }
 
 static void
-sflt_detach_locked(
-       struct socket_filter_entry      *entry)
+sflt_detach_locked(struct socket_filter_entry *entry)
 {
        if ((entry->sfe_flags & SFEF_ATTACHED) != 0) {
                entry->sfe_flags &= ~SFEF_ATTACHED;
@@ -369,40 +382,51 @@ sflt_detach_locked(
 #pragma mark -- Socket Layer Hooks --
 
 __private_extern__ void
-sflt_initsock(
-       struct socket *so)
+sflt_initsock(struct socket *so)
 {
-       struct protosw *proto = so->so_proto;
-       
+       /*
+        * Point to the real protosw, as so_proto might have been
+        * pointed to a modified version.
+        */
+       struct protosw *proto = so->so_proto->pr_protosw;
+
        lck_rw_lock_shared(sock_filter_lock);
        if (TAILQ_FIRST(&proto->pr_filter_head) != NULL) {
-               // Promote lock to exclusive
+               /* Promote lock to exclusive */
                if (!lck_rw_lock_shared_to_exclusive(sock_filter_lock))
                        lck_rw_lock_exclusive(sock_filter_lock);
-               
-               // Warning: A filter unregistering will be pulled out of the list.
-               // This could happen while we drop the lock in sftl_attach_locked
-               // or sflt_release_locked. For this reason we retain a reference
-               // on the filter (or next_filter) while calling this function
-               //
-               // This protects us from a panic, but it could result in a
-               // socket being created without all of the global filters if
-               // we're attaching a filter as it is removed, if that's possible.
-               struct socket_filter *filter = TAILQ_FIRST(&proto->pr_filter_head);
+
+               /*
+                * Warning: A filter unregistering will be pulled out of
+                * the list.  This could happen while we drop the lock in
+                * sftl_attach_locked or sflt_release_locked.  For this
+                * reason we retain a reference on the filter (or next_filter)
+                * while calling this function.  This protects us from a panic,
+                * but it could result in a socket being created without all
+                * of the global filters if we're attaching a filter as it
+                * is removed, if that's possible.
+                */
+               struct socket_filter *filter =
+                   TAILQ_FIRST(&proto->pr_filter_head);
+
                sflt_retain_locked(filter);
-               
-               while (filter)
-               {
+
+               while (filter) {
                        struct socket_filter *filter_next;
-                       
-                       // Warning: sflt_attach_private_locked will drop the lock
+                       /*
+                        * Warning: sflt_attach_private_locked
+                        * will drop the lock
+                        */
                        sflt_attach_locked(so, filter, 0);
-                       
+
                        filter_next = TAILQ_NEXT(filter, sf_protosw_next);
                        if (filter_next)
                                sflt_retain_locked(filter_next);
-                       
-                       // Warning: filt_release_locked may remove the filter from the queue
+
+                       /*
+                        * Warning: filt_release_locked may remove
+                        * the filter from the queue
+                        */
                        sflt_release_locked(filter);
                        filter = filter_next;
                }
@@ -415,146 +439,150 @@ sflt_initsock(
  *
  * Detaches all filters from the socket.
  */
-
 __private_extern__ void
-sflt_termsock(
-       struct socket *so)
+sflt_termsock(struct socket *so)
 {
        lck_rw_lock_exclusive(sock_filter_lock);
-       
+
        struct socket_filter_entry *entry;
-       
+
        while ((entry = so->so_filt) != NULL) {
-               // Pull filter off the socket
+               /* Pull filter off the socket */
                so->so_filt = entry->sfe_next_onsocket;
                entry->sfe_flags |= SFEF_NOSOCKET;
-               
-               // Call detach
+
+               /* Call detach */
                sflt_detach_locked(entry);
-               
-               // On sflt_termsock, we can't return until the detach function has been called
-               // Call the detach function - this is gross because the socket filter
-               // entry could be freed when we drop the lock, so we make copies on
-               // the stack and retain everything we need before dropping the lock
+
+               /*
+                * On sflt_termsock, we can't return until the detach function
+                * has been called.  Call the detach function - this is gross
+                * because the socket filter entry could be freed when we drop
+                * the lock, so we make copies on  the stack and retain
+                * everything we need before dropping the lock.
+                */
                if ((entry->sfe_flags & SFEF_NODETACH) == 0 &&
-                       entry->sfe_filter->sf_filter.sf_detach) {
-                       void                                    *sfe_cookie = entry->sfe_cookie;
-                       struct socket_filter    *sfe_filter = entry->sfe_filter;
-                       
-                       // Retain the socket filter
+                   entry->sfe_filter->sf_filter.sf_detach) {
+                       void *sfe_cookie = entry->sfe_cookie;
+                       struct socket_filter *sfe_filter = entry->sfe_filter;
+
+                       /* Retain the socket filter */
                        sflt_retain_locked(sfe_filter);
-                       
-                       // Mark that we've called the detach function
+
+                       /* Mark that we've called the detach function */
                        entry->sfe_flags |= SFEF_NODETACH;
-                       
-                       // Drop the lock around the call to the detach function
+
+                       /* Drop the lock before calling the detach function */
                        lck_rw_unlock_exclusive(sock_filter_lock);
                        sfe_filter->sf_filter.sf_detach(sfe_cookie, so);
                        lck_rw_lock_exclusive(sock_filter_lock);
-                       
-                       // Release the filter
+
+                       /* Release the filter */
                        sflt_release_locked(sfe_filter);
                }
        }
-       
+
        lck_rw_unlock_exclusive(sock_filter_lock);
 }
 
 
 static void
-sflt_notify_internal(
-       struct socket   *so,
-       sflt_event_t    event,
-       void            *param,
-       sflt_handle     handle)
+sflt_notify_internal(struct socket *so, sflt_event_t event, void *param,
+    sflt_handle handle)
 {
-       if (so->so_filt == NULL) return;
-       
-       struct socket_filter_entry      *entry;
-       int                             unlocked = 0;
-       
+       if (so->so_filt == NULL)
+               return;
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry; entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                   && entry->sfe_filter->sf_filter.sf_notify &&
-                   ((handle && entry->sfe_filter->sf_filter.sf_handle != handle) ||
-                    !handle)) {
-                       // Retain the filter entry and release the socket filter lock
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_notify &&
+                   ((handle && entry->sfe_filter->sf_filter.sf_handle !=
+                   handle) || !handle)) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                unlocked = 1;
                                socket_unlock(so, 0);
                        }
-                       
-                       // Finally call the filter
-                       entry->sfe_filter->sf_filter.
-                               sf_notify(entry->sfe_cookie, so, event, param);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Finally call the filter */
+                       entry->sfe_filter->sf_filter.sf_notify(
+                           entry->sfe_cookie, so, event, param);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
        }
        lck_rw_unlock_shared(sock_filter_lock);
-       
+
        if (unlocked != 0) {
                socket_lock(so, 0);
        }
 }
 
 __private_extern__ void
-sflt_notify(
-       struct socket   *so,
-       sflt_event_t    event,
-       void            *param)
+sflt_notify(struct socket *so, sflt_event_t event, void         *param)
 {
        sflt_notify_internal(so, event, param, 0);
 }
 
 static void
-sflt_notify_after_register(
-       struct socket   *so,
-       sflt_event_t    event,
-       sflt_handle     handle)
+sflt_notify_after_register(struct socket *so, sflt_event_t event,
+    sflt_handle handle)
 {
        sflt_notify_internal(so, event, NULL, handle);
 }
 
 __private_extern__ int
-sflt_ioctl(
-       struct socket   *so,
-       u_long                  cmd,
-       caddr_t                 data)
+sflt_ioctl(struct socket *so, u_long cmd, caddr_t data)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_ioctl) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_ioctl) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_ioctl(entry->sfe_cookie, so, cmd, data);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_ioctl(
+                           entry->sfe_cookie, so, cmd, data);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -564,41 +592,46 @@ sflt_ioctl(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_bind(
-       struct socket                   *so,
-       const struct sockaddr   *nam)
+sflt_bind(struct socket *so, const struct sockaddr *nam)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_bind) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_bind) {
+                       /*
+                        * Retain the filter entry and
+                        * release the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_bind(entry->sfe_cookie, so, nam);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_bind(
+                           entry->sfe_cookie, so, nam);
+
+                       /*
+                        * Take the socket filter lock again and
+                        * release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -608,40 +641,46 @@ sflt_bind(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_listen(
-       struct socket                   *so)
+sflt_listen(struct socket *so)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_listen) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_listen) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_listen(entry->sfe_cookie, so);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_listen(
+                           entry->sfe_cookie, so);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -651,43 +690,47 @@ sflt_listen(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_accept(
-       struct socket                   *head,
-       struct socket                   *so,
-       const struct sockaddr   *local,
-       const struct sockaddr   *remote)
+sflt_accept(struct socket *head, struct socket *so,
+    const struct sockaddr *local, const struct sockaddr *remote)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_accept) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_accept) {
+                       /*
+                        * Retain the filter entry and
+                        * release the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_accept(entry->sfe_cookie, head, so, local, remote);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_accept(
+                           entry->sfe_cookie, head, so, local, remote);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -697,41 +740,46 @@ sflt_accept(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_getsockname(
-       struct socket                   *so,
-       struct sockaddr                 **local)
+sflt_getsockname(struct socket *so, struct sockaddr **local)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_getsockname) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_getsockname) {
+                       /*
+                        * Retain the filter entry and
+                        * release the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_getsockname(entry->sfe_cookie, so, local);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_getsockname(
+                           entry->sfe_cookie, so, local);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -741,41 +789,46 @@ sflt_getsockname(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_getpeername(
-       struct socket                   *so,
-       struct sockaddr                 **remote)
+sflt_getpeername(struct socket *so, struct sockaddr **remote)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_getpeername) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_getpeername) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_getpeername(entry->sfe_cookie, so, remote);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_getpeername(
+                           entry->sfe_cookie, so, remote);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -785,41 +838,46 @@ sflt_getpeername(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_connectin(
-       struct socket                   *so,
-       const struct sockaddr   *remote)
+sflt_connectin(struct socket *so, const struct sockaddr        *remote)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_connect_in) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_connect_in) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_connect_in(entry->sfe_cookie, so, remote);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_connect_in(
+                           entry->sfe_cookie, so, remote);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -829,41 +887,46 @@ sflt_connectin(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_connectout(
-       struct socket                   *so,
-       const struct sockaddr   *nam)
+sflt_connectout(struct socket *so, const struct sockaddr *nam)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_connect_out) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_connect_out) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_connect_out(entry->sfe_cookie, so, nam);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_connect_out(
+                           entry->sfe_cookie, so, nam);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -873,41 +936,101 @@ sflt_connectout(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
+}
+
+__private_extern__ int
+sflt_connectxout(struct socket *so, struct sockaddr_list **dst_sl0)
+{
+       char buf[SOCK_MAXADDRLEN];
+       struct sockaddr_list *dst_sl;
+       struct sockaddr_entry *se, *tse;
+       int modified = 0;
+       int error = 0;
+
+       if (so->so_filt == NULL)
+               return (0);
+
+       /* make a copy as sflt_connectout() releases socket lock */
+       dst_sl = sockaddrlist_dup(*dst_sl0, M_WAITOK);
+       if (dst_sl == NULL)
+               return (ENOBUFS);
+
+       /*
+        * Hmm; we don't yet have a connectx socket filter callback,
+        * so the closest thing to do is to probably call sflt_connectout()
+        * as many times as there are addresses in the list, and bail
+        * as soon as we get an error.
+        */
+       TAILQ_FOREACH_SAFE(se, &dst_sl->sl_head, se_link, tse) {
+               int sa_len = se->se_addr->sa_len;
+
+               /* remember the original address */
+               bzero(buf, sizeof (buf));
+               bcopy(se->se_addr, buf, sa_len);
+
+               VERIFY(se->se_addr != NULL);
+               error = sflt_connectout(so, se->se_addr);
+               if (error != 0)
+                       break;
+
+               /* see if the address was modified */
+               if (bcmp(se->se_addr, buf, sa_len) != 0)
+                       modified = 1;
+       }
+
+       if (error != 0 || !modified) {
+               /* leave the original as is */
+               sockaddrlist_free(dst_sl);
+       } else {
+               /*
+                * At least one address was modified and there were no errors;
+                * ditch the original and return the modified list.
+                */
+               sockaddrlist_free(*dst_sl0);
+               *dst_sl0 = dst_sl;
+       }
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_setsockopt(
-       struct socket   *so,
-       struct sockopt  *sopt)
+sflt_setsockopt(struct socket *so, struct sockopt *sopt)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_setoption) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_setoption) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_setoption(entry->sfe_cookie, so, sopt);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_setoption(
+                           entry->sfe_cookie, so, sopt);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -917,41 +1040,46 @@ sflt_setsockopt(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_getsockopt(
-       struct socket   *so,
-       struct sockopt  *sopt)
+sflt_getsockopt(struct socket *so, struct sockopt *sopt)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_getoption) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_getoption) {
+                       /*
+                        * Retain the filter entry and release
+                        * the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_getoption(entry->sfe_cookie, so, sopt);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_getoption(
+                           entry->sfe_cookie, so, sopt);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -961,49 +1089,56 @@ sflt_getsockopt(
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_data_out(
-       struct socket                   *so,
-       const struct sockaddr   *to,
-       mbuf_t                                  *data,
-       mbuf_t                                  *control,
-       sflt_data_flag_t                flags)
+sflt_data_out(struct socket *so, const struct sockaddr *to, mbuf_t *data,
+    mbuf_t *control, sflt_data_flag_t flags)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     unlocked = 0;
-       int                                                     setsendthread = 0;
-       int                                                     error = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int unlocked = 0;
+       int setsendthread = 0;
+       int error = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
        for (entry = so->so_filt; entry && error == 0;
-                entry = entry->sfe_next_onsocket) {
-               if ((entry->sfe_flags & SFEF_ATTACHED)
-                       && entry->sfe_filter->sf_filter.sf_data_out) {
-                       // Retain the filter entry and release the socket filter lock
+           entry = entry->sfe_next_onsocket) {
+               /* skip if this is a subflow socket */
+               if (so->so_flags & SOF_MP_SUBFLOW)
+                       continue;
+               if ((entry->sfe_flags & SFEF_ATTACHED) &&
+                   entry->sfe_filter->sf_filter.sf_data_out) {
+                       /*
+                        * Retain the filter entry and
+                        * release the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                if (so->so_send_filt_thread == NULL) {
                                        setsendthread = 1;
-                                       so->so_send_filt_thread = current_thread();
+                                       so->so_send_filt_thread =
+                                           current_thread();
                                }
                                socket_unlock(so, 0);
                                unlocked = 1;
                        }
-                       
-                       // Call the filter
-                       error = entry->sfe_filter->sf_filter.
-                               sf_data_out(entry->sfe_cookie, so, to, data, control, flags);
-                       
-                       // Take the socket filter lock again and release the entry
+
+                       /* Call the filter */
+                       error = entry->sfe_filter->sf_filter.sf_data_out(
+                           entry->sfe_cookie, so, to, data, control, flags);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
@@ -1012,99 +1147,101 @@ sflt_data_out(
 
        if (unlocked) {
                socket_lock(so, 0);
-               if (setsendthread) so->so_send_filt_thread = NULL;
+               if (setsendthread)
+                       so->so_send_filt_thread = NULL;
        }
-       
-       return error;
+
+       return (error);
 }
 
 __private_extern__ int
-sflt_data_in(
-       struct socket                   *so,
-       const struct sockaddr   *from,
-       mbuf_t                                  *data,
-       mbuf_t                                  *control,
-       sflt_data_flag_t                flags)
+sflt_data_in(struct socket *so, const struct sockaddr *from, mbuf_t *data,
+    mbuf_t *control, sflt_data_flag_t flags)
 {
-       if (so->so_filt == NULL) return 0;
-       
-       struct socket_filter_entry      *entry;
-       int                                                     error = 0;
-       int                                                     unlocked = 0;
-       
+       if (so->so_filt == NULL)
+               return (0);
+
+       struct socket_filter_entry *entry;
+       int error = 0;
+       int unlocked = 0;
+
        lck_rw_lock_shared(sock_filter_lock);
-       
+
        for (entry = so->so_filt; entry && (error == 0);
-                entry = entry->sfe_next_onsocket) {
+           entry = entry->sfe_next_onsocket) {
+               /* skip if this is a subflow socket */
+               if (so->so_flags & SOF_MP_SUBFLOW)
+                       continue;
                if ((entry->sfe_flags & SFEF_ATTACHED) &&
-                       entry->sfe_filter->sf_filter.sf_data_in) {
-                       // Retain the filter entry and release the socket filter lock
+                   entry->sfe_filter->sf_filter.sf_data_in) {
+                       /*
+                        * Retain the filter entry and
+                        * release the socket filter lock
+                        */
                        sflt_entry_retain(entry);
                        lck_rw_unlock_shared(sock_filter_lock);
-                       
-                       // If the socket isn't already unlocked, unlock it
+
+                       /* If the socket isn't already unlocked, unlock it */
                        if (unlocked == 0) {
                                unlocked = 1;
                                socket_unlock(so, 0);
                        }
-                       
-                       // Call the filter
+
+                       /* Call the filter */
                        error = entry->sfe_filter->sf_filter.sf_data_in(
-                                               entry->sfe_cookie, so, from, data, control, flags);
-                       
-                       // Take the socket filter lock again and release the entry
+                           entry->sfe_cookie, so, from, data, control, flags);
+
+                       /*
+                        * Take the socket filter lock again
+                        * and release the entry
+                        */
                        lck_rw_lock_shared(sock_filter_lock);
                        sflt_entry_release(entry);
                }
        }
        lck_rw_unlock_shared(sock_filter_lock);
-       
+
        if (unlocked) {
                socket_lock(so, 0);
        }
-       
-       return error;
+
+       return (error);
 }
 
 #pragma mark -- KPI --
 
 errno_t
-sflt_attach(
-       socket_t        socket,
-       sflt_handle     handle)
+sflt_attach(socket_t socket, sflt_handle handle)
 {
        socket_lock(socket, 1);
        errno_t result = sflt_attach_internal(socket, handle);
        socket_unlock(socket, 1);
-       return result;
+       return (result);
 }
 
 errno_t
-sflt_detach(
-       socket_t        socket,
-       sflt_handle     handle)
+sflt_detach(socket_t socket, sflt_handle handle)
 {
-       struct socket_filter_entry      *entry;
+       struct socket_filter_entry *entry;
        errno_t result = 0;
-       
+
        if (socket == NULL || handle == 0)
-               return EINVAL;
-       
+               return (EINVAL);
+
        lck_rw_lock_exclusive(sock_filter_lock);
-       for (entry = socket->so_filt; entry;
-                entry = entry->sfe_next_onsocket) {
+       for (entry = socket->so_filt; entry; entry = entry->sfe_next_onsocket) {
                if (entry->sfe_filter->sf_filter.sf_handle == handle &&
-                       (entry->sfe_flags & SFEF_ATTACHED) != 0) {
+                   (entry->sfe_flags & SFEF_ATTACHED) != 0) {
                        break;
                }
        }
-       
+
        if (entry != NULL) {
                sflt_detach_locked(entry);
        }
        lck_rw_unlock_exclusive(sock_filter_lock);
-       
-       return result;
+
+       return (result);
 }
 
 struct solist {
@@ -1113,11 +1250,8 @@ struct solist {
 };
 
 errno_t
-sflt_register(
-       const struct sflt_filter        *filter,
-       int                             domain,
-       int                             type,
-       int                             protocol)
+sflt_register(const struct sflt_filter *filter, int domain, int type,
+    int         protocol)
 {
        struct socket_filter *sock_filt = NULL;
        struct socket_filter *match = NULL;
@@ -1129,17 +1263,17 @@ sflt_register(
        struct solist *solisthead = NULL, *solist = NULL;
 
        if (pr == NULL)
-               return ENOENT;
+               return (ENOENT);
 
        if (filter->sf_attach == NULL || filter->sf_detach == NULL ||
            filter->sf_handle == 0 || filter->sf_name == NULL)
-               return EINVAL;
+               return (EINVAL);
 
        /* Allocate the socket filter */
        MALLOC(sock_filt, struct socket_filter *, sizeof (*sock_filt),
            M_IFADDR, M_WAITOK);
        if (sock_filt == NULL) {
-               return ENOBUFS;
+               return (ENOBUFS);
        }
 
        bzero(sock_filt, sizeof (*sock_filt));
@@ -1169,7 +1303,7 @@ sflt_register(
                        break;
                }
        }
-       
+
        /* Add the entry only if there was no existing entry */
        if (match == NULL) {
                TAILQ_INSERT_TAIL(&sock_filter_head, sock_filt, sf_global_next);
@@ -1184,53 +1318,55 @@ sflt_register(
 
        if (match != NULL) {
                FREE(sock_filt, M_IFADDR);
-               return EEXIST;
+               return (EEXIST);
        }
 
        if (!(filter->sf_flags & SFLT_EXTENDED_REGISTRY))
-               return error;
+               return (error);
 
        /*
         * Setup the filter on the TCP and UDP sockets already created.
         */
-#define SOLIST_ADD(_so)                do {                                    \
+#define        SOLIST_ADD(_so) do {                                            \
        solist->next = solisthead;                                      \
        sock_retain((_so));                                             \
        solist->so = (_so);                                             \
        solisthead = solist;                                            \
 } while (0)
        if (protocol == IPPROTO_TCP) {
-               lck_rw_lock_shared(tcbinfo.mtx);
-               LIST_FOREACH(inp, tcbinfo.listhead, inp_list) {
+               lck_rw_lock_shared(tcbinfo.ipi_lock);
+               LIST_FOREACH(inp, tcbinfo.ipi_listhead, inp_list) {
                        so = inp->inp_socket;
-                       if (so == NULL || so->so_state & SS_DEFUNCT ||
-                           so->so_state & SS_NOFDREF ||
-                           !INP_CHECK_SOCKAF(so, domain) ||
-                           !INP_CHECK_SOCKTYPE(so, type))
+                       if (so == NULL || (so->so_state & SS_DEFUNCT) ||
+                           (!(so->so_flags & SOF_MP_SUBFLOW) &&
+                           (so->so_state & SS_NOFDREF)) ||
+                           !SOCK_CHECK_DOM(so, domain) ||
+                           !SOCK_CHECK_TYPE(so, type))
                                continue;
-                       MALLOC(solist, struct solist *, sizeof(*solist),
+                       MALLOC(solist, struct solist *, sizeof (*solist),
                            M_IFADDR, M_NOWAIT);
                        if (!solist)
                                continue;
                        SOLIST_ADD(so);
                }
-               lck_rw_done(tcbinfo.mtx);
+               lck_rw_done(tcbinfo.ipi_lock);
        } else if (protocol == IPPROTO_UDP) {
-               lck_rw_lock_shared(udbinfo.mtx);
-               LIST_FOREACH(inp, udbinfo.listhead, inp_list) {
+               lck_rw_lock_shared(udbinfo.ipi_lock);
+               LIST_FOREACH(inp, udbinfo.ipi_listhead, inp_list) {
                        so = inp->inp_socket;
-                       if (so == NULL || so->so_state & SS_DEFUNCT ||
-                           so->so_state & SS_NOFDREF ||
-                           !INP_CHECK_SOCKAF(so, domain) ||
-                           !INP_CHECK_SOCKTYPE(so, type))
+                       if (so == NULL || (so->so_state & SS_DEFUNCT) ||
+                           (!(so->so_flags & SOF_MP_SUBFLOW) &&
+                           (so->so_state & SS_NOFDREF)) ||
+                           !SOCK_CHECK_DOM(so, domain) ||
+                           !SOCK_CHECK_TYPE(so, type))
                                continue;
-                       MALLOC(solist, struct solist *, sizeof(*solist),
+                       MALLOC(solist, struct solist *, sizeof (*solist),
                            M_IFADDR, M_NOWAIT);
                        if (!solist)
                                continue;
                        SOLIST_ADD(so);
                }
-               lck_rw_done(udbinfo.mtx);
+               lck_rw_done(udbinfo.ipi_lock);
        }
        /* XXX it's possible to walk the raw socket list as well */
 #undef SOLIST_ADD
@@ -1270,153 +1406,150 @@ sflt_register(
                FREE(solist, M_IFADDR);
        }
 
-       return error;
+       return (error);
 }
 
 errno_t
-sflt_unregister(
-       sflt_handle handle)
+sflt_unregister(sflt_handle handle)
 {
        struct socket_filter *filter;
        lck_rw_lock_exclusive(sock_filter_lock);
-       
+
        /* Find the entry by the handle */
        TAILQ_FOREACH(filter, &sock_filter_head, sf_global_next) {
                if (filter->sf_filter.sf_handle == handle)
                        break;
        }
-       
+
        if (filter) {
-               // Remove it from the global list
+               /* Remove it from the global list */
                TAILQ_REMOVE(&sock_filter_head, filter, sf_global_next);
-               
-               // Remove it from the protosw list
+
+               /* Remove it from the protosw list */
                if ((filter->sf_filter.sf_flags & SFLT_GLOBAL) != 0) {
-                       TAILQ_REMOVE(&filter->sf_proto->pr_filter_head, filter, sf_protosw_next);
+                       TAILQ_REMOVE(&filter->sf_proto->pr_filter_head,
+                           filter, sf_protosw_next);
                }
-               
-               // Detach from any sockets
+
+               /* Detach from any sockets */
                struct socket_filter_entry *entry = NULL;
-               
-               for (entry = filter->sf_entry_head; entry; entry = entry->sfe_next_onfilter) {
+
+               for (entry = filter->sf_entry_head; entry;
+                   entry = entry->sfe_next_onfilter) {
                        sflt_detach_locked(entry);
                }
-               
-               // Release the filter
+
+               /* Release the filter */
                sflt_release_locked(filter);
        }
-       
+
        lck_rw_unlock_exclusive(sock_filter_lock);
-       
+
        if (filter == NULL)
-               return ENOENT;
-       
-       return 0;
+               return (ENOENT);
+
+       return (0);
 }
 
 errno_t
-sock_inject_data_in(
-       socket_t so,
-       const struct sockaddr* from,
-       mbuf_t data,
-       mbuf_t control,
-       sflt_data_flag_t flags)
+sock_inject_data_in(socket_t so, const struct sockaddr *from, mbuf_t data,
+    mbuf_t control, sflt_data_flag_t flags)
 {
        int error = 0;
-       if (so == NULL || data == NULL) return EINVAL;
-       
+
+       if (so == NULL || data == NULL)
+               return (EINVAL);
+
        if (flags & sock_data_filt_flag_oob) {
-               return ENOTSUP;
+               return (ENOTSUP);
        }
-       
+
        socket_lock(so, 1);
-       
+
+       /* reject if this is a subflow socket */
+       if (so->so_flags & SOF_MP_SUBFLOW) {
+               error = ENOTSUP;
+               goto done;
+       }
+
        if (from) {
-               if (sbappendaddr(&so->so_rcv, (struct sockaddr*)(uintptr_t)from, data,
-                                                control, NULL))
+               if (sbappendaddr(&so->so_rcv,
+                   (struct sockaddr *)(uintptr_t)from, data, control, NULL))
                        sorwakeup(so);
                goto done;
        }
-       
+
        if (control) {
                if (sbappendcontrol(&so->so_rcv, data, control, NULL))
                        sorwakeup(so);
                goto done;
        }
-       
+
        if (flags & sock_data_filt_flag_record) {
                if (control || from) {
                        error = EINVAL;
                        goto done;
                }
-               if (sbappendrecord(&so->so_rcv, (struct mbuf*)data))
+               if (sbappendrecord(&so->so_rcv, (struct mbuf *)data))
                        sorwakeup(so);
                goto done;
        }
-       
+
        if (sbappend(&so->so_rcv, data))
                sorwakeup(so);
 done:
        socket_unlock(so, 1);
-       return error;
+       return (error);
 }
 
 errno_t
-sock_inject_data_out(
-       socket_t so,
-       const struct sockaddr* to,
-       mbuf_t data,
-       mbuf_t control,
-       sflt_data_flag_t flags)
+sock_inject_data_out(socket_t so, const struct sockaddr *to, mbuf_t data,
+    mbuf_t control, sflt_data_flag_t flags)
 {
-       int     sosendflags = 0;
-       if (flags & sock_data_filt_flag_oob) sosendflags = MSG_OOB;
-       return sosend(so, (struct sockaddr*)(uintptr_t)to, NULL,
-                                 data, control, sosendflags);
+       int sosendflags = 0;
+
+       /* reject if this is a subflow socket */
+       if (so->so_flags & SOF_MP_SUBFLOW)
+               return (ENOTSUP);
+
+       if (flags & sock_data_filt_flag_oob)
+               sosendflags = MSG_OOB;
+       return (sosend(so, (struct sockaddr *)(uintptr_t)to, NULL,
+           data, control, sosendflags));
 }
 
 sockopt_dir
-sockopt_direction(
-       sockopt_t       sopt)
+sockopt_direction(sockopt_t sopt)
 {
-       return (sopt->sopt_dir == SOPT_GET) ? sockopt_get : sockopt_set;
+       return ((sopt->sopt_dir == SOPT_GET) ? sockopt_get : sockopt_set);
 }
 
 int
-sockopt_level(
-       sockopt_t       sopt)
+sockopt_level(sockopt_t sopt)
 {
-       return sopt->sopt_level;
+       return (sopt->sopt_level);
 }
 
 int
-sockopt_name(
-       sockopt_t       sopt)
+sockopt_name(sockopt_t sopt)
 {
-       return sopt->sopt_name;
+       return (sopt->sopt_name);
 }
 
 size_t
-sockopt_valsize(
-       sockopt_t       sopt)
+sockopt_valsize(sockopt_t sopt)
 {
-       return sopt->sopt_valsize;
+       return (sopt->sopt_valsize);
 }
 
 errno_t
-sockopt_copyin(
-       sockopt_t       sopt,
-       void *data,
-       size_t  len)
+sockopt_copyin(sockopt_t sopt, void *data, size_t len)
 {
-       return sooptcopyin(sopt, data, len, len);
+       return (sooptcopyin(sopt, data, len, len));
 }
 
 errno_t
-sockopt_copyout(
-       sockopt_t       sopt,
-       void *data,
-       size_t  len)
+sockopt_copyout(sockopt_t sopt, void *data, size_t len)
 {
-       return sooptcopyout(sopt, data, len);
+       return (sooptcopyout(sopt, data, len));
 }