2  * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * The contents of this file constitute Original Code as defined in and 
   7  * are subject to the Apple Public Source License Version 1.1 (the 
   8  * "License").  You may not use this file except in compliance with the 
   9  * License.  Please obtain a copy of the License at 
  10  * http://www.apple.com/publicsource and read it before using this file. 
  12  * This Original Code and all software distributed under the License are 
  13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the 
  17  * License for the specific language governing rights and limitations 
  20  * @APPLE_LICENSE_HEADER_END@ 
  23  * Copyright (c) 1982, 1986, 1990, 1993 
  24  *      The Regents of the University of California.  All rights reserved. 
  26  * Redistribution and use in source and binary forms, with or without 
  27  * modification, are permitted provided that the following conditions 
  29  * 1. Redistributions of source code must retain the above copyright 
  30  *    notice, this list of conditions and the following disclaimer. 
  31  * 2. Redistributions in binary form must reproduce the above copyright 
  32  *    notice, this list of conditions and the following disclaimer in the 
  33  *    documentation and/or other materials provided with the distribution. 
  34  * 3. All advertising materials mentioning features or use of this software 
  35  *    must display the following acknowledgement: 
  36  *      This product includes software developed by the University of 
  37  *      California, Berkeley and its contributors. 
  38  * 4. Neither the name of the University nor the names of its contributors 
  39  *    may be used to endorse or promote products derived from this software 
  40  *    without specific prior written permission. 
  42  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  43  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  45  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  46  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  48  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  54  *      @(#)sys_socket.c        8.1 (Berkeley) 6/10/93 
  57 #include <sys/param.h> 
  58 #include <sys/systm.h> 
  59 #include <sys/file_internal.h> 
  60 #include <sys/event.h> 
  61 #include <sys/protosw.h> 
  62 #include <sys/socket.h> 
  63 #include <sys/socketvar.h> 
  64 #include <sys/filio.h>                  /* XXX */ 
  65 #include <sys/sockio.h> 
  68 #include <sys/filedesc.h> 
  69 #include <sys/kauth.h> 
  70 #include <sys/signalvar.h> 
  73 #include <net/route.h> 
  76  * File operations on sockets. 
  78 int     soo_read(struct fileproc 
*fp
, struct uio 
*uio
, kauth_cred_t cred
, 
  79                 int flags
, struct proc 
*p
); 
  80 int     soo_write(struct fileproc 
*fp
, struct uio 
*uio
, kauth_cred_t cred
, 
  81                 int flags
, struct proc 
*p
); 
  82 int soo_close(struct fileglob 
*fp
, struct proc 
*p
); 
  83 int     soo_ioctl(struct fileproc 
*fp
, u_long cmd
, caddr_t data
, struct proc 
*p
); 
  84 int     soo_stat(struct socket 
*so
, struct stat 
*ub
); 
  85 int     soo_select(struct fileproc 
*fp
, int which
, void * wql
, struct proc 
*p
); 
  86 int     soo_kqfilter(struct fileproc 
*fp
, struct knote 
*kn
, struct proc 
*p
); 
  87 int     soo_drain(struct fileproc 
*fp
, struct proc 
*p
); 
  89 struct  fileops socketops 
= 
  90     { soo_read
, soo_write
, soo_ioctl
, soo_select
, soo_close
, soo_kqfilter
, soo_drain 
}; 
  97         __unused kauth_cred_t cred
, 
  99         __unused 
struct proc 
*p
) 
 103         int (*fsoreceive
)(struct socket 
*so2
,  
 104                                struct sockaddr 
**paddr
, 
 105                                struct uio 
*uio2
, struct mbuf 
**mp0
, 
 106                                struct mbuf 
**controlp
, int *flagsp
); 
 110         if ((so 
= (struct socket 
*)fp
->f_fglob
->fg_data
) == NULL
) { 
 111                 /* This is not a valid open file descriptor */ 
 114 //###LD will have to change 
 115         fsoreceive 
= so
->so_proto
->pr_usrreqs
->pru_soreceive
; 
 117         stat 
= (*fsoreceive
)(so
, 0, uio
, 0, 0, 0); 
 126         __unused kauth_cred_t cred
, 
 131         int     (*fsosend
)(struct socket 
*so2
, struct sockaddr 
*addr
, 
 132                                 struct uio 
*uio2
, struct mbuf 
*top
, 
 133                                 struct mbuf 
*control
, int flags2
); 
 136         if ((so 
= (struct socket 
*)fp
->f_fglob
->fg_data
) == NULL
) { 
 137                 /* This is not a valid open file descriptor */ 
 141         fsosend 
= so
->so_proto
->pr_usrreqs
->pru_sosend
; 
 143         stat 
= (*fsosend
)(so
, 0, uio
, 0, 0, 0); 
 145         /* Generation of SIGPIPE can be controlled per socket */ 
 146         if (stat 
== EPIPE 
&& procp 
&& !(so
->so_flags 
& SOF_NOSIGPIPE
)) 
 147                 psignal(procp
, SIGPIPE
); 
 152 __private_extern__ 
int 
 161         int dropsockref 
= -1; 
 166         sopt
.sopt_level 
= cmd
; 
 167         sopt
.sopt_name 
= (int)data
; 
 174                         so
->so_state 
|= SS_NBIO
; 
 176                         so
->so_state 
&= ~SS_NBIO
; 
 182                         so
->so_state 
|= SS_ASYNC
; 
 183                         so
->so_rcv
.sb_flags 
|= SB_ASYNC
; 
 184                         so
->so_snd
.sb_flags 
|= SB_ASYNC
; 
 186                         so
->so_state 
&= ~SS_ASYNC
; 
 187                         so
->so_rcv
.sb_flags 
&= ~SB_ASYNC
; 
 188                         so
->so_snd
.sb_flags 
&= ~SB_ASYNC
; 
 193                 *(int *)data 
= so
->so_rcv
.sb_cc
; 
 197                 so
->so_pgid 
= *(int *)data
; 
 201                 *(int *)data 
= so
->so_pgid
; 
 205              *(int *)data 
= (so
->so_state
&SS_RCVATMARK
) != 0; 
 210               * Set socket level options here and then call protocol 
 213              struct socket      
*cloned_so 
= NULL
; 
 214              int                                cloned_fd 
= *(int *)data
; 
 216              /* let's make sure it's either -1 or a valid file descriptor */ 
 217              if (cloned_fd 
!= -1) { 
 218                   error 
= file_socket(cloned_fd
, &cloned_so
); 
 222                  dropsockref 
= cloned_fd
; 
 225              /* Always set socket non-blocking for OT */ 
 226              so
->so_state 
|= SS_NBIO
; 
 227              so
->so_options 
|= SO_DONTTRUNC 
| SO_WANTMORE
; 
 228           so
->so_flags 
|= SOF_NOSIGPIPE
; 
 230              if (cloned_so 
&& so 
!= cloned_so
) { 
 232                   so
->so_options 
|= cloned_so
->so_options 
& ~SO_ACCEPTCONN
; 
 235             if (so
->so_options 
& SO_LINGER
) 
 236                 so
->so_linger 
= cloned_so
->so_linger
; 
 238             /* SO_SNDBUF, SO_RCVBUF */ 
 239                   if (cloned_so
->so_snd
.sb_hiwat 
> 0) { 
 240                        if (sbreserve(&so
->so_snd
, cloned_so
->so_snd
.sb_hiwat
) == 0) { 
 245                   if (cloned_so
->so_rcv
.sb_hiwat 
> 0) { 
 246                        if (sbreserve(&so
->so_rcv
, cloned_so
->so_rcv
.sb_hiwat
) == 0) { 
 252                   /* SO_SNDLOWAT, SO_RCVLOWAT */ 
 253                   so
->so_snd
.sb_lowat 
= 
 254                        (cloned_so
->so_snd
.sb_lowat 
> so
->so_snd
.sb_hiwat
) ? 
 255                        so
->so_snd
.sb_hiwat 
: cloned_so
->so_snd
.sb_lowat
; 
 256                   so
->so_rcv
.sb_lowat 
= 
 257                        (cloned_so
->so_rcv
.sb_lowat 
> so
->so_rcv
.sb_hiwat
) ? 
 258                        so
->so_rcv
.sb_hiwat 
: cloned_so
->so_rcv
.sb_lowat
; 
 260                   /* SO_SNDTIMEO, SO_RCVTIMEO */ 
 261                   so
->so_snd
.sb_timeo 
= cloned_so
->so_snd
.sb_timeo
; 
 262                   so
->so_rcv
.sb_timeo 
= cloned_so
->so_rcv
.sb_timeo
; 
 265              error 
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
, cmd
, data
, 0, p
); 
 266              /* Just ignore protocols that do not understand it */ 
 267              if (error 
== EOPNOTSUPP
) 
 274          * Interface/routing/protocol specific ioctls: 
 275          * interface and routing ioctls should have a 
 276          * different entry since a socket's unnecessary 
 278         if (IOCGROUP(cmd
) == 'i') 
 279              error 
= ifioctllocked(so
, cmd
, data
, p
); 
 281              if (IOCGROUP(cmd
) == 'r') 
 282                   error 
= rtioctl(cmd
, data
, p
); 
 284                   error 
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
, cmd
, data
, 0, p
); 
 287         if (dropsockref 
!= -1) 
 288                 file_drop(dropsockref
); 
 289         socket_unlock(so
, 1); 
 295 soo_ioctl(fp
, cmd
, data
, p
) 
 298         register caddr_t data
; 
 301         register struct socket 
*so
; 
 305         if ((so 
= (struct socket 
*)fp
->f_fglob
->fg_data
) == NULL
) { 
 306                 /* This is not a valid open file descriptor */ 
 310         error 
= soioctl(so
, cmd
, data
, p
); 
 312         if (error 
== 0 && cmd 
== SIOCSETOT
) 
 313                 fp
->f_fglob
->fg_flag 
|= FNONBLOCK
; 
 319 soo_select(fp
, which
, wql
, p
) 
 325         register struct socket 
*so 
= (struct socket 
*)fp
->f_fglob
->fg_data
; 
 328         if (so 
== NULL 
|| so 
== (struct socket
*)-1) 
 335                 so
->so_rcv
.sb_flags 
|= SB_SEL
; 
 336                 if (soreadable(so
)) { 
 338                         so
->so_rcv
.sb_flags 
&= ~SB_SEL
; 
 341                 selrecord(p
, &so
->so_rcv
.sb_sel
, wql
); 
 345                 so
->so_snd
.sb_flags 
|= SB_SEL
; 
 346                 if (sowriteable(so
)) { 
 348                         so
->so_snd
.sb_flags 
&= ~SB_SEL
; 
 351                 selrecord(p
, &so
->so_snd
.sb_sel
, wql
); 
 355                 so
->so_rcv
.sb_flags 
|= SB_SEL
; 
 356                 if (so
->so_oobmark 
|| (so
->so_state 
& SS_RCVATMARK
)) { 
 358                         so
->so_rcv
.sb_flags 
&= ~SB_SEL
; 
 361                 selrecord(p
, &so
->so_rcv
.sb_sel
, wql
); 
 366         socket_unlock(so
, 1); 
 373         register struct socket 
*so
; 
 374         register struct stat 
*ub
; 
 378         bzero((caddr_t
)ub
, sizeof (*ub
)); 
 380         ub
->st_mode 
= S_IFSOCK
; 
 381         stat 
= (*so
->so_proto
->pr_usrreqs
->pru_sense
)(so
, ub
); 
 382         socket_unlock(so
, 1); 
 388 soo_close(struct fileglob 
*fg
, __unused proc_t p
) 
 393         sp 
= (struct socket 
*)fg
->fg_data
; 
 405 soo_drain(struct fileproc 
*fp
, __unused 
struct proc 
*p
) 
 408         struct socket 
*so 
= (struct socket 
*)fp
->f_fglob
->fg_data
; 
 412                 so
->so_state 
|= SS_DRAINING
; 
 414                 wakeup((caddr_t
)&so
->so_timeo
); 
 418                 socket_unlock(so
, 1);