]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/raw_usrreq.c
   2  * Copyright (c) 2000-2012 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Copyright (c) 1980, 1986, 1993 
  30  *      The Regents of the University of California.  All rights reserved. 
  32  * Redistribution and use in source and binary forms, with or without 
  33  * modification, are permitted provided that the following conditions 
  35  * 1. Redistributions of source code must retain the above copyright 
  36  *    notice, this list of conditions and the following disclaimer. 
  37  * 2. Redistributions in binary form must reproduce the above copyright 
  38  *    notice, this list of conditions and the following disclaimer in the 
  39  *    documentation and/or other materials provided with the distribution. 
  40  * 3. All advertising materials mentioning features or use of this software 
  41  *    must display the following acknowledgement: 
  42  *      This product includes software developed by the University of 
  43  *      California, Berkeley and its contributors. 
  44  * 4. Neither the name of the University nor the names of its contributors 
  45  *    may be used to endorse or promote products derived from this software 
  46  *    without specific prior written permission. 
  48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  60  *      @(#)raw_usrreq.c        8.1 (Berkeley) 6/10/93 
  61  * $FreeBSD: src/sys/net/raw_usrreq.c,v 1.18 1999/08/28 00:48:28 peter Exp $ 
  64 #include <sys/param.h> 
  65 #include <sys/systm.h> 
  68 #include <sys/domain.h> 
  69 #include <sys/protosw.h> 
  70 #include <sys/socket.h> 
  71 #include <sys/socketvar.h> 
  72 #include <kern/locks.h> 
  74 #include <net/raw_cb.h> 
  76 decl_lck_mtx_data(, raw_mtx_data
);       /*### global raw cb mutex for now */ 
  77 lck_mtx_t       
*raw_mtx 
= &raw_mtx_data
; 
  78 lck_attr_t      
*raw_mtx_attr
; 
  79 lck_grp_t       
*raw_mtx_grp
; 
  80 lck_grp_attr_t  
*raw_mtx_grp_attr
; 
  82  * Initialize raw connection block q. 
  85 raw_init(struct protosw 
*pp
, struct domain 
*dp
) 
  87 #pragma unused(pp, dp) 
  88         static int raw_initialized 
= 0; 
  90         /* This is called by key_init as well, so do it only once */ 
  91         if (!raw_initialized
) { 
  94                 raw_mtx_grp_attr 
= lck_grp_attr_alloc_init(); 
  95                 raw_mtx_grp 
= lck_grp_alloc_init("rawcb", raw_mtx_grp_attr
); 
  96                 raw_mtx_attr 
= lck_attr_alloc_init(); 
  98                 lck_mtx_init(raw_mtx
, raw_mtx_grp
, raw_mtx_attr
); 
  99                 LIST_INIT(&rawcb_list
); 
 105  * Raw protocol input routine.  Find the socket 
 106  * associated with the packet(s) and move them over.  If 
 107  * nothing exists for this packet, drop it. 
 110  * Raw protocol interface. 
 113 raw_input(struct mbuf 
*m0
, struct sockproto 
*proto
, struct sockaddr 
*src
, 
 114     struct sockaddr 
*dst
) 
 122 //####LD raw_input is called from many places, input & output path. We have to assume the 
 123 //####LD socket we'll find and need to append to is unlocked. 
 124 //####LD calls from the output (locked) path need to make sure the socket is not locked when 
 125 //####LD we call in raw_input 
 127         lck_mtx_lock(raw_mtx
); 
 128         LIST_FOREACH(rp
, &rawcb_list
, list
) { 
 129                 if (rp
->rcb_proto
.sp_family 
!= proto
->sp_family
) { 
 132                 if (rp
->rcb_proto
.sp_protocol 
&& 
 133                     rp
->rcb_proto
.sp_protocol 
!= proto
->sp_protocol
) { 
 137                  * We assume the lower level routines have 
 138                  * placed the address in a canonical format 
 139                  * suitable for a structure comparison. 
 141                  * Note that if the lengths are not the same 
 142                  * the comparison will fail at the first byte. 
 144 #define equal(a1, a2) \ 
 145   (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 
 146                 if (rp
->rcb_laddr 
&& !equal(rp
->rcb_laddr
, dst
)) { 
 149                 if (rp
->rcb_faddr 
&& !equal(rp
->rcb_faddr
, src
)) { 
 154                         n 
= m_copy(m
, 0, (int)M_COPYALL
); 
 156                                 socket_lock(last
, 1); 
 157                                 if (sbappendaddr(&last
->so_rcv
, src
, 
 158                                     n
, (struct mbuf 
*)0, &error
) != 0) { 
 162                                 socket_unlock(last
, 1); 
 165                 last 
= rp
->rcb_socket
; 
 168                 socket_lock(last
, 1); 
 169                 if (sbappendaddr(&last
->so_rcv
, src
, 
 170                     m
, (struct mbuf 
*)0, &error
) != 0) { 
 174                 socket_unlock(last
, 1); 
 178         lck_mtx_unlock(raw_mtx
); 
 183 raw_ctlinput(int cmd
, __unused 
struct sockaddr 
*arg
, __unused 
void *dummy
, 
 184     __unused 
struct ifnet 
*ifp
) 
 186         if (cmd 
< 0 || cmd 
>= PRC_NCMDS
) { 
 193 raw_uabort(struct socket 
*so
) 
 195         struct rawcb 
*rp 
= sotorawcb(so
); 
 197         lck_mtx_t 
* mutex_held
; 
 198         if (so
->so_proto
->pr_getlock 
!= NULL
) { 
 199                 mutex_held 
= (*so
->so_proto
->pr_getlock
)(so
, 0); 
 201                 mutex_held 
= so
->so_proto
->pr_domain
->dom_mtx
; 
 203         LCK_MTX_ASSERT(mutex_held
, LCK_MTX_ASSERT_OWNED
); 
 210         soisdisconnected(so
); 
 214 /* pru_accept is EOPNOTSUPP */ 
 217 raw_uattach(struct socket 
*so
, int proto
, __unused 
struct proc 
*p
) 
 219         struct rawcb 
*rp 
= sotorawcb(so
); 
 224         if ((so
->so_state 
& SS_PRIV
) == 0) { 
 227         return raw_attach(so
, proto
); 
 231 raw_ubind(__unused 
struct socket 
*so
, __unused 
struct sockaddr 
*nam
, __unused 
struct proc 
*p
) 
 237 raw_uconnect(__unused 
struct socket 
*so
, __unused 
struct sockaddr 
*nam
, __unused 
struct proc 
*p
) 
 242 /* pru_connect2 is EOPNOTSUPP */ 
 243 /* pru_control is EOPNOTSUPP */ 
 246 raw_udetach(struct socket 
*so
) 
 248         struct rawcb 
*rp 
= sotorawcb(so
); 
 250         lck_mtx_t 
* mutex_held
; 
 251         if (so
->so_proto
->pr_getlock 
!= NULL
) { 
 252                 mutex_held 
= (*so
->so_proto
->pr_getlock
)(so
, 0); 
 254                 mutex_held 
= so
->so_proto
->pr_domain
->dom_mtx
; 
 256         LCK_MTX_ASSERT(mutex_held
, LCK_MTX_ASSERT_OWNED
); 
 266 raw_udisconnect(struct socket 
*so
) 
 268         struct rawcb 
*rp 
= sotorawcb(so
); 
 273         if (rp
->rcb_faddr 
== 0) { 
 277         soisdisconnected(so
); 
 281 /* pru_listen is EOPNOTSUPP */ 
 284 raw_upeeraddr(struct socket 
*so
, struct sockaddr 
**nam
) 
 286         struct rawcb 
*rp 
= sotorawcb(so
); 
 291         if (rp
->rcb_faddr 
== 0) { 
 294         *nam 
= dup_sockaddr(rp
->rcb_faddr
, 1); 
 298 /* pru_rcvd is EOPNOTSUPP */ 
 299 /* pru_rcvoob is EOPNOTSUPP */ 
 302 raw_usend(struct socket 
*so
, int flags
, struct mbuf 
*m
, 
 303     struct sockaddr 
*nam
, struct mbuf 
*control
, __unused 
struct proc 
*p
) 
 306         struct rawcb 
*rp 
= sotorawcb(so
); 
 308         lck_mtx_t 
* mutex_held
; 
 309         if (so
->so_proto
->pr_getlock 
!= NULL
) { 
 310                 mutex_held 
= (*so
->so_proto
->pr_getlock
)(so
, 0); 
 312                 mutex_held 
= so
->so_proto
->pr_domain
->dom_mtx
; 
 314         LCK_MTX_ASSERT(mutex_held
, LCK_MTX_ASSERT_OWNED
); 
 321         if (flags 
& PRUS_OOB
) { 
 326         if (so
->so_proto
->pr_output 
== NULL
) { 
 331         if (control 
!= NULL
) { 
 342         } else if (rp
->rcb_faddr 
== 0) { 
 346         error 
= (*so
->so_proto
->pr_output
)(m
, so
); 
 349                 rp
->rcb_faddr 
= NULL
; 
 358 /* pru_sense is null */ 
 361 raw_ushutdown(struct socket 
*so
) 
 363         struct rawcb 
*rp 
= sotorawcb(so
); 
 364         lck_mtx_t 
* mutex_held
; 
 365         if (so
->so_proto
->pr_getlock 
!= NULL
) { 
 366                 mutex_held 
= (*so
->so_proto
->pr_getlock
)(so
, 0); 
 368                 mutex_held 
= so
->so_proto
->pr_domain
->dom_mtx
; 
 370         LCK_MTX_ASSERT(mutex_held
, LCK_MTX_ASSERT_OWNED
); 
 380 raw_usockaddr(struct socket 
*so
, struct sockaddr 
**nam
) 
 382         struct rawcb 
*rp 
= sotorawcb(so
); 
 387         if (rp
->rcb_laddr 
== 0) { 
 390         *nam 
= dup_sockaddr(rp
->rcb_laddr
, 1); 
 394 struct pr_usrreqs raw_usrreqs 
= { 
 395         .pru_abort 
=            raw_uabort
, 
 396         .pru_attach 
=           raw_uattach
, 
 397         .pru_bind 
=             raw_ubind
, 
 398         .pru_connect 
=          raw_uconnect
, 
 399         .pru_detach 
=           raw_udetach
, 
 400         .pru_disconnect 
=       raw_udisconnect
, 
 401         .pru_peeraddr 
=         raw_upeeraddr
, 
 402         .pru_send 
=             raw_usend
, 
 403         .pru_shutdown 
=         raw_ushutdown
, 
 404         .pru_sockaddr 
=         raw_usockaddr
, 
 405         .pru_sosend 
=           sosend
, 
 406         .pru_soreceive 
=        soreceive
,