2  * Copyright (c) 2003 Apple Computer, 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 <kern/locks.h> 
  37 #include <net/kext_net.h> 
  39 static struct socket_filter_list        sock_filter_head
; 
  40 static lck_mtx_t                                        
*sock_filter_lock 
= 0; 
  42 static void     sflt_detach_private(struct socket_filter_entry 
*entry
, int unregistering
); 
  44 __private_extern__ 
void 
  47         lck_grp_attr_t  
*grp_attrib 
= 0; 
  48         lck_attr_t              
*lck_attrib 
= 0; 
  49         lck_grp_t               
*lck_group 
= 0; 
  51         TAILQ_INIT(&sock_filter_head
); 
  53         /* Allocate a spin lock */ 
  54         grp_attrib 
= lck_grp_attr_alloc_init(); 
  55         lck_group 
= lck_grp_alloc_init("socket filter lock", grp_attrib
); 
  56         lck_grp_attr_free(grp_attrib
); 
  57         lck_attrib 
= lck_attr_alloc_init(); 
  58         sock_filter_lock 
= lck_mtx_alloc_init(lck_group
, lck_attrib
); 
  59         lck_grp_free(lck_group
); 
  60         lck_attr_free(lck_attrib
); 
  63 __private_extern__ 
void 
  67         struct protosw 
*proto 
= so
->so_proto
; 
  68         struct socket_filter 
*filter
; 
  70         if (TAILQ_FIRST(&proto
->pr_filter_head
) != NULL
) { 
  71                 lck_mtx_lock(sock_filter_lock
); 
  72                 TAILQ_FOREACH(filter
, &proto
->pr_filter_head
, sf_protosw_next
) { 
  73                         sflt_attach_private(so
, filter
, 0, 0); 
  75                 lck_mtx_unlock(sock_filter_lock
); 
  79 __private_extern__ 
void 
  83         struct socket_filter_entry 
*filter
; 
  84         struct socket_filter_entry 
*filter_next
; 
  86         for (filter 
= so
->so_filt
; filter
; filter 
= filter_next
) { 
  87                 filter_next 
= filter
->sfe_next_onsocket
; 
  88                 sflt_detach_private(filter
, 0); 
  93 __private_extern__ 
void 
 100 __private_extern__ 
void 
 105         if (so
->so_filteruse 
== 0) { 
 106                 struct socket_filter_entry 
*filter
; 
 107                 struct socket_filter_entry 
*next_filter
; 
 108                 // search for detaching filters 
 109                 for (filter 
= so
->so_filt
; filter
; filter 
= next_filter
) { 
 110                         next_filter 
= filter
->sfe_next_onsocket
; 
 112                         if (filter
->sfe_flags 
& SFEF_DETACHUSEZERO
) { 
 113                                 sflt_detach_private(filter
, 0); 
 119 __private_extern__ 
void 
 125         struct socket_filter_entry      
*filter
; 
 128         for (filter 
= so
->so_filt
; filter
; 
 129                  filter 
= filter
->sfe_next_onsocket
) { 
 130                 if (filter
->sfe_filter
->sf_filter
.sf_notify
) { 
 134                                 socket_unlock(so
, 0); 
 136                         filter
->sfe_filter
->sf_filter
.sf_notify( 
 137                                 filter
->sfe_cookie
, so
, event
, param
); 
 147 __private_extern__ 
int 
 150         const struct sockaddr   
*from
, 
 153         sflt_data_flag_t                flags
, 
 156         struct socket_filter_entry      
*filter
; 
 158         int                                                     filtered_storage
; 
 160         if (filtered 
== NULL
) 
 161                 filtered 
= &filtered_storage
; 
 164         for (filter 
= so
->so_filt
; filter 
&& (error 
== 0); 
 165                  filter 
= filter
->sfe_next_onsocket
) { 
 166                 if (filter
->sfe_filter
->sf_filter
.sf_data_in
) { 
 167                         if (*filtered 
== 0) { 
 170                                 socket_unlock(so
, 0); 
 172                         error 
= filter
->sfe_filter
->sf_filter
.sf_data_in( 
 173                                                 filter
->sfe_cookie
, so
, from
, data
, control
, flags
); 
 177         if (*filtered 
!= 0) { 
 185 /* sflt_attach_private 
 187  * Assumptions: If filter is not NULL, socket_filter_lock is held. 
 190 __private_extern__ 
int 
 193         struct socket_filter 
*filter
, 
 197         struct socket_filter_entry 
*entry 
= NULL
; 
 201         if (filter 
== NULL
) { 
 202                 /* Find the filter by the handle */ 
 203                 lck_mtx_lock(sock_filter_lock
); 
 206                 TAILQ_FOREACH(filter
, &sock_filter_head
, sf_global_next
) { 
 207                         if (filter
->sf_filter
.sf_handle 
== handle
) 
 216                 /* allocate the socket filter entry */ 
 217                 MALLOC(entry
, struct socket_filter_entry 
*, sizeof(*entry
), M_IFADDR
, M_WAITOK
); 
 224                 /* Initialize the socket filter entry and call the attach function */ 
 225                 entry
->sfe_filter 
= filter
; 
 226                 entry
->sfe_socket 
= so
; 
 227                 entry
->sfe_cookie 
= NULL
; 
 228                 entry
->sfe_flags 
= 0; 
 229                 if (entry
->sfe_filter
->sf_filter
.sf_attach
) { 
 230                         filter
->sf_usecount
++; 
 233                                 socket_unlock(so
, 0);    
 234                         error 
= entry
->sfe_filter
->sf_filter
.sf_attach(&entry
->sfe_cookie
, so
); 
 238                         filter
->sf_usecount
--; 
 240                         /* If the attach function returns an error, this filter is not attached */ 
 242                                 FREE(entry
, M_IFADDR
); 
 249                 /* Put the entry in the socket list */ 
 250                 entry
->sfe_next_onsocket 
= so
->so_filt
; 
 253                 /* Put the entry in the filter list */ 
 254                 entry
->sfe_next_onfilter 
= filter
->sf_entry_head
; 
 255                 filter
->sf_entry_head 
= entry
; 
 257                 /* Incremenet the parent filter's usecount */ 
 258                 filter
->sf_usecount
++; 
 262                 lck_mtx_unlock(sock_filter_lock
); 
 269 /* sflt_detach_private 
 271  * Assumptions: if you pass 0 in for the second parameter, you are holding the 
 272  * socket lock for the socket the entry is attached to. If you pass 1 in for 
 273  * the second parameter, it is assumed that the entry is not on the filter's 
 274  * list and the socket lock is not held. 
 279         struct socket_filter_entry 
*entry
, 
 282         struct socket 
*so 
= entry
->sfe_socket
; 
 283         struct socket_filter_entry 
**next_ptr
; 
 288                 socket_lock(entry
->sfe_socket
, 0); 
 292          * Attempt to find the entry on the filter's list and 
 293          * remove it. This prevents a filter detaching at the 
 294          * same time from attempting to remove the same entry. 
 296         lck_mtx_lock(sock_filter_lock
); 
 297         if (!unregistering
) { 
 298                 if ((entry
->sfe_flags 
& SFEF_UNREGISTERING
) != 0) { 
 300                          * Another thread is unregistering the filter, we need to 
 301                          * avoid detaching the filter here so the socket won't go 
 304                         lck_mtx_unlock(sock_filter_lock
); 
 307                 for (next_ptr 
= &entry
->sfe_filter
->sf_entry_head
; *next_ptr
; 
 308                          next_ptr 
= &((*next_ptr
)->sfe_next_onfilter
)) { 
 309                         if (*next_ptr 
== entry
) { 
 311                                 *next_ptr 
= entry
->sfe_next_onfilter
; 
 316                 if (!found 
&& (entry
->sfe_flags 
& SFEF_DETACHUSEZERO
) == 0) { 
 317                         lck_mtx_unlock(sock_filter_lock
); 
 323                  * Clear the removing flag. We will perform the detach here or 
 324                  * request a delayed deatch. 
 326                 entry
->sfe_flags 
&= ~SFEF_UNREGISTERING
; 
 329         if (entry
->sfe_socket
->so_filteruse 
!= 0) { 
 330                 entry
->sfe_flags 
|= SFEF_DETACHUSEZERO
; 
 331                 lck_mtx_unlock(sock_filter_lock
); 
 336                  * Check if we are removing the last attached filter and 
 337                  * the parent filter is being unregistered. 
 339                 entry
->sfe_filter
->sf_usecount
--; 
 340                 if ((entry
->sfe_filter
->sf_usecount 
== 0) && 
 341                         (entry
->sfe_filter
->sf_flags 
& SFF_DETACHING
) != 0) 
 344         lck_mtx_unlock(sock_filter_lock
); 
 346         /* Remove from the socket list */ 
 347         for (next_ptr 
= &entry
->sfe_socket
->so_filt
; *next_ptr
; 
 348                  next_ptr 
= &((*next_ptr
)->sfe_next_onsocket
)) { 
 349                 if (*next_ptr 
== entry
) { 
 350                         *next_ptr 
= entry
->sfe_next_onsocket
; 
 355         if (entry
->sfe_filter
->sf_filter
.sf_detach
) 
 356                 entry
->sfe_filter
->sf_filter
.sf_detach(entry
->sfe_cookie
, entry
->sfe_socket
); 
 358         if (detached 
&& entry
->sfe_filter
->sf_filter
.sf_unregistered
) { 
 359                 entry
->sfe_filter
->sf_filter
.sf_unregistered(entry
->sfe_filter
->sf_filter
.sf_handle
); 
 360                 FREE(entry
->sfe_filter
, M_IFADDR
); 
 364                 socket_unlock(entry
->sfe_socket
, 1); 
 366         FREE(entry
, M_IFADDR
); 
 374         if (socket 
== NULL 
|| handle 
== 0) 
 377         return sflt_attach_private(socket
, NULL
, handle
, 0); 
 385         struct socket_filter_entry      
*filter
; 
 388         if (socket 
== NULL 
|| handle 
== 0) 
 391         socket_lock(socket
, 1); 
 393         for (filter 
= socket
->so_filt
; filter
; 
 394                  filter 
= filter
->sfe_next_onsocket
) { 
 395                 if (filter
->sfe_filter
->sf_filter
.sf_handle 
== handle
) 
 399         if (filter 
!= NULL
) { 
 400                 sflt_detach_private(filter
, 0); 
 403                 socket
->so_filt 
= NULL
; 
 407         socket_unlock(socket
, 1); 
 415         const struct sflt_filter        
*filter
, 
 420         struct socket_filter 
*sock_filt 
= NULL
; 
 421         struct socket_filter 
*match 
= NULL
; 
 423         struct protosw 
*pr 
= pffindproto(domain
, protocol
, type
); 
 425         if (pr 
== NULL
) return ENOENT
; 
 427         if (filter
->sf_attach 
== NULL 
|| filter
->sf_detach 
== NULL
) return EINVAL
; 
 428         if (filter
->sf_handle 
== 0) return EINVAL
; 
 429         if (filter
->sf_name 
== NULL
) return EINVAL
; 
 431         /* Allocate the socket filter */ 
 432         MALLOC(sock_filt
, struct socket_filter
*, sizeof(*sock_filt
), M_IFADDR
, M_WAITOK
); 
 433         if (sock_filt 
== NULL
) { 
 437         bzero(sock_filt
, sizeof(*sock_filt
)); 
 438         sock_filt
->sf_filter 
= *filter
; 
 440         lck_mtx_lock(sock_filter_lock
); 
 441         /* Look for an existing entry */ 
 442         TAILQ_FOREACH(match
, &sock_filter_head
, sf_global_next
) { 
 443                 if (match
->sf_filter
.sf_handle 
== sock_filt
->sf_filter
.sf_handle
) { 
 448         /* Add the entry only if there was no existing entry */ 
 450                 TAILQ_INSERT_TAIL(&sock_filter_head
, sock_filt
, sf_global_next
); 
 451                 if ((sock_filt
->sf_filter
.sf_flags 
& SFLT_GLOBAL
) != 0) { 
 452                         TAILQ_INSERT_TAIL(&pr
->pr_filter_head
, sock_filt
, sf_protosw_next
); 
 453                         sock_filt
->sf_proto 
= pr
; 
 456         lck_mtx_unlock(sock_filter_lock
); 
 459                 FREE(sock_filt
, M_IFADDR
); 
 470         struct socket_filter 
*filter
; 
 471         struct socket_filter_entry 
*entry_head 
= NULL
; 
 472         struct socket_filter_entry 
*next_entry 
= NULL
; 
 474         /* Find the entry and remove it from the global and protosw lists */ 
 475         lck_mtx_lock(sock_filter_lock
); 
 476         TAILQ_FOREACH(filter
, &sock_filter_head
, sf_global_next
) { 
 477                 if (filter
->sf_filter
.sf_handle 
== handle
) 
 482                 TAILQ_REMOVE(&sock_filter_head
, filter
, sf_global_next
); 
 483                 if ((filter
->sf_filter
.sf_flags 
& SFLT_GLOBAL
) != 0) { 
 484                         TAILQ_REMOVE(&filter
->sf_proto
->pr_filter_head
, filter
, sf_protosw_next
); 
 486                 entry_head 
= filter
->sf_entry_head
; 
 487                 filter
->sf_entry_head 
= NULL
; 
 488                 filter
->sf_flags 
|= SFF_DETACHING
; 
 490                 for (next_entry 
= entry_head
; next_entry
; 
 491                          next_entry 
= next_entry
->sfe_next_onfilter
) { 
 492                         socket_lock(next_entry
->sfe_socket
, 1); 
 493                         next_entry
->sfe_flags 
|= SFEF_UNREGISTERING
; 
 494                         socket_unlock(next_entry
->sfe_socket
, 0);       /* Radar 4201550: prevents the socket from being deleted while being unregistered */ 
 498         lck_mtx_unlock(sock_filter_lock
); 
 503         /* We need to detach the filter from any sockets it's attached to */ 
 504         if (entry_head 
== 0) { 
 505                 if (filter
->sf_filter
.sf_unregistered
) 
 506                         filter
->sf_filter
.sf_unregistered(filter
->sf_filter
.sf_handle
); 
 509                         next_entry 
= entry_head
->sfe_next_onfilter
; 
 510                         sflt_detach_private(entry_head
, 1); 
 511                         entry_head 
= next_entry
; 
 521         const struct sockaddr
* from
, 
 524         sflt_data_flag_t flags
) 
 527         if (so 
== NULL 
|| data 
== NULL
) return EINVAL
; 
 529         if (flags 
& sock_data_filt_flag_oob
) { 
 536                 if (sbappendaddr(&so
->so_rcv
, (struct sockaddr
*)from
, data
, 
 543                 if (sbappendcontrol(&so
->so_rcv
, data
, control
, NULL
)) 
 548         if (flags 
& sock_data_filt_flag_record
) { 
 549                 if (control 
|| from
) { 
 553                 if (sbappendrecord(&so
->so_rcv
, (struct mbuf
*)data
)) 
 558         if (sbappend(&so
->so_rcv
, data
)) 
 561         socket_unlock(so
, 1); 
 566 sock_inject_data_out( 
 568         const struct sockaddr
* to
, 
 571         sflt_data_flag_t flags
) 
 574         if (flags 
& sock_data_filt_flag_oob
) sosendflags 
= MSG_OOB
; 
 575         return sosend(so
, (const struct sockaddr
*)to
, NULL
, 
 576                                   data
, control
, sosendflags
); 
 583         return (sopt
->sopt_dir 
== SOPT_GET
) ? sockopt_get 
: sockopt_set
; 
 590         return sopt
->sopt_level
; 
 597         return sopt
->sopt_name
; 
 604         return sopt
->sopt_valsize
; 
 613         return sooptcopyin(sopt
, data
, len
, len
); 
 622         return sooptcopyout(sopt
, data
, len
);