2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1982, 1986, 1990, 1993
32 * The Regents of the University of California. All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
46 * 4. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/file_internal.h>
68 #include <sys/event.h>
69 #include <sys/protosw.h>
70 #include <sys/socket.h>
71 #include <sys/socketvar.h>
72 #include <sys/filio.h> /* XXX */
73 #include <sys/sockio.h>
76 #include <sys/filedesc.h>
77 #include <sys/kauth.h>
78 #include <sys/signalvar.h>
81 #include <net/route.h>
84 * File operations on sockets.
86 int soo_read(struct fileproc
*fp
, struct uio
*uio
, kauth_cred_t cred
,
87 int flags
, struct proc
*p
);
88 int soo_write(struct fileproc
*fp
, struct uio
*uio
, kauth_cred_t cred
,
89 int flags
, struct proc
*p
);
90 int soo_close(struct fileglob
*fp
, struct proc
*p
);
91 int soo_ioctl(struct fileproc
*fp
, u_long cmd
, caddr_t data
, struct proc
*p
);
92 int soo_stat(struct socket
*so
, struct stat
*ub
);
93 int soo_select(struct fileproc
*fp
, int which
, void * wql
, struct proc
*p
);
94 int soo_kqfilter(struct fileproc
*fp
, struct knote
*kn
, struct proc
*p
);
95 int soo_drain(struct fileproc
*fp
, struct proc
*p
);
97 struct fileops socketops
=
98 { soo_read
, soo_write
, soo_ioctl
, soo_select
, soo_close
, soo_kqfilter
, soo_drain
};
105 __unused kauth_cred_t cred
,
107 __unused
struct proc
*p
)
111 int (*fsoreceive
)(struct socket
*so2
,
112 struct sockaddr
**paddr
,
113 struct uio
*uio2
, struct mbuf
**mp0
,
114 struct mbuf
**controlp
, int *flagsp
);
118 if ((so
= (struct socket
*)fp
->f_fglob
->fg_data
) == NULL
) {
119 /* This is not a valid open file descriptor */
122 //###LD will have to change
123 fsoreceive
= so
->so_proto
->pr_usrreqs
->pru_soreceive
;
125 stat
= (*fsoreceive
)(so
, 0, uio
, 0, 0, 0);
134 __unused kauth_cred_t cred
,
139 int (*fsosend
)(struct socket
*so2
, struct sockaddr
*addr
,
140 struct uio
*uio2
, struct mbuf
*top
,
141 struct mbuf
*control
, int flags2
);
144 if ((so
= (struct socket
*)fp
->f_fglob
->fg_data
) == NULL
) {
145 /* This is not a valid open file descriptor */
149 fsosend
= so
->so_proto
->pr_usrreqs
->pru_sosend
;
151 stat
= (*fsosend
)(so
, 0, uio
, 0, 0, 0);
153 /* Generation of SIGPIPE can be controlled per socket */
154 if (stat
== EPIPE
&& procp
&& !(so
->so_flags
& SOF_NOSIGPIPE
))
155 psignal(procp
, SIGPIPE
);
160 __private_extern__
int
169 int dropsockref
= -1;
174 sopt
.sopt_level
= cmd
;
175 sopt
.sopt_name
= (int)data
;
182 so
->so_state
|= SS_NBIO
;
184 so
->so_state
&= ~SS_NBIO
;
190 so
->so_state
|= SS_ASYNC
;
191 so
->so_rcv
.sb_flags
|= SB_ASYNC
;
192 so
->so_snd
.sb_flags
|= SB_ASYNC
;
194 so
->so_state
&= ~SS_ASYNC
;
195 so
->so_rcv
.sb_flags
&= ~SB_ASYNC
;
196 so
->so_snd
.sb_flags
&= ~SB_ASYNC
;
201 *(int *)data
= so
->so_rcv
.sb_cc
;
205 so
->so_pgid
= *(int *)data
;
209 *(int *)data
= so
->so_pgid
;
213 *(int *)data
= (so
->so_state
&SS_RCVATMARK
) != 0;
218 * Set socket level options here and then call protocol
221 struct socket
*cloned_so
= NULL
;
222 int cloned_fd
= *(int *)data
;
224 /* let's make sure it's either -1 or a valid file descriptor */
225 if (cloned_fd
!= -1) {
226 error
= file_socket(cloned_fd
, &cloned_so
);
230 dropsockref
= cloned_fd
;
233 /* Always set socket non-blocking for OT */
234 so
->so_state
|= SS_NBIO
;
235 so
->so_options
|= SO_DONTTRUNC
| SO_WANTMORE
;
236 so
->so_flags
|= SOF_NOSIGPIPE
;
238 if (cloned_so
&& so
!= cloned_so
) {
240 so
->so_options
|= cloned_so
->so_options
& ~SO_ACCEPTCONN
;
243 if (so
->so_options
& SO_LINGER
)
244 so
->so_linger
= cloned_so
->so_linger
;
246 /* SO_SNDBUF, SO_RCVBUF */
247 if (cloned_so
->so_snd
.sb_hiwat
> 0) {
248 if (sbreserve(&so
->so_snd
, cloned_so
->so_snd
.sb_hiwat
) == 0) {
253 if (cloned_so
->so_rcv
.sb_hiwat
> 0) {
254 if (sbreserve(&so
->so_rcv
, cloned_so
->so_rcv
.sb_hiwat
) == 0) {
260 /* SO_SNDLOWAT, SO_RCVLOWAT */
261 so
->so_snd
.sb_lowat
=
262 (cloned_so
->so_snd
.sb_lowat
> so
->so_snd
.sb_hiwat
) ?
263 so
->so_snd
.sb_hiwat
: cloned_so
->so_snd
.sb_lowat
;
264 so
->so_rcv
.sb_lowat
=
265 (cloned_so
->so_rcv
.sb_lowat
> so
->so_rcv
.sb_hiwat
) ?
266 so
->so_rcv
.sb_hiwat
: cloned_so
->so_rcv
.sb_lowat
;
268 /* SO_SNDTIMEO, SO_RCVTIMEO */
269 so
->so_snd
.sb_timeo
= cloned_so
->so_snd
.sb_timeo
;
270 so
->so_rcv
.sb_timeo
= cloned_so
->so_rcv
.sb_timeo
;
273 error
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
, cmd
, data
, 0, p
);
274 /* Just ignore protocols that do not understand it */
275 if (error
== EOPNOTSUPP
)
282 * Interface/routing/protocol specific ioctls:
283 * interface and routing ioctls should have a
284 * different entry since a socket's unnecessary
286 if (IOCGROUP(cmd
) == 'i')
287 error
= ifioctllocked(so
, cmd
, data
, p
);
289 if (IOCGROUP(cmd
) == 'r')
290 error
= rtioctl(cmd
, data
, p
);
292 error
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
, cmd
, data
, 0, p
);
295 if (dropsockref
!= -1)
296 file_drop(dropsockref
);
297 socket_unlock(so
, 1);
303 soo_ioctl(fp
, cmd
, data
, p
)
306 register caddr_t data
;
309 register struct socket
*so
;
313 if ((so
= (struct socket
*)fp
->f_fglob
->fg_data
) == NULL
) {
314 /* This is not a valid open file descriptor */
318 error
= soioctl(so
, cmd
, data
, p
);
320 if (error
== 0 && cmd
== SIOCSETOT
)
321 fp
->f_fglob
->fg_flag
|= FNONBLOCK
;
327 soo_select(fp
, which
, wql
, p
)
333 register struct socket
*so
= (struct socket
*)fp
->f_fglob
->fg_data
;
336 if (so
== NULL
|| so
== (struct socket
*)-1)
343 so
->so_rcv
.sb_flags
|= SB_SEL
;
344 if (soreadable(so
)) {
346 so
->so_rcv
.sb_flags
&= ~SB_SEL
;
349 selrecord(p
, &so
->so_rcv
.sb_sel
, wql
);
353 so
->so_snd
.sb_flags
|= SB_SEL
;
354 if (sowriteable(so
)) {
356 so
->so_snd
.sb_flags
&= ~SB_SEL
;
359 selrecord(p
, &so
->so_snd
.sb_sel
, wql
);
363 so
->so_rcv
.sb_flags
|= SB_SEL
;
364 if (so
->so_oobmark
|| (so
->so_state
& SS_RCVATMARK
)) {
366 so
->so_rcv
.sb_flags
&= ~SB_SEL
;
369 selrecord(p
, &so
->so_rcv
.sb_sel
, wql
);
374 socket_unlock(so
, 1);
381 register struct socket
*so
;
382 register struct stat
*ub
;
386 bzero((caddr_t
)ub
, sizeof (*ub
));
388 ub
->st_mode
= S_IFSOCK
;
389 stat
= (*so
->so_proto
->pr_usrreqs
->pru_sense
)(so
, ub
);
390 socket_unlock(so
, 1);
396 soo_close(struct fileglob
*fg
, __unused proc_t p
)
401 sp
= (struct socket
*)fg
->fg_data
;
413 soo_drain(struct fileproc
*fp
, __unused
struct proc
*p
)
416 struct socket
*so
= (struct socket
*)fp
->f_fglob
->fg_data
;
420 so
->so_state
|= SS_DRAINING
;
422 wakeup((caddr_t
)&so
->so_timeo
);
426 socket_unlock(so
, 1);