2 * Copyright (c) 2000-2011 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) 1982, 1986, 1990, 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 * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93
63 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
64 * support for mandatory and extensible security protections. This notice
65 * is included in support of clause 2.2 (b) of the Apple Public License,
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/file_internal.h>
72 #include <sys/event.h>
73 #include <sys/protosw.h>
74 #include <sys/socket.h>
75 #include <sys/socketvar.h>
76 #include <sys/filio.h> /* XXX */
77 #include <sys/sockio.h>
80 #include <sys/filedesc.h>
81 #include <sys/kauth.h>
82 #include <sys/signalvar.h>
83 #include <sys/vnode.h>
86 #include <net/route.h>
89 #include <security/mac_framework.h>
93 * File operations on sockets.
95 static int soo_read(struct fileproc
*, struct uio
*, int, vfs_context_t ctx
);
96 static int soo_write(struct fileproc
*, struct uio
*, int, vfs_context_t ctx
);
97 static int soo_close(struct fileglob
*, vfs_context_t ctx
);
98 static int soo_drain(struct fileproc
*, vfs_context_t ctx
);
100 /* TODO: these should be in header file */
101 extern int soo_ioctl(struct fileproc
*, u_long
, caddr_t
, vfs_context_t ctx
);
102 extern int soo_stat(struct socket
*, void *, int);
103 extern int soo_select(struct fileproc
*, int, void *, vfs_context_t ctx
);
104 extern int soo_kqfilter(struct fileproc
*, struct knote
*, vfs_context_t ctx
);
106 struct fileops socketops
= {
107 soo_read
, soo_write
, soo_ioctl
, soo_select
, soo_close
,
108 soo_kqfilter
, soo_drain
113 soo_read(struct fileproc
*fp
, struct uio
*uio
, __unused
int flags
,
114 #if !CONFIG_MACF_SOCKET
121 #if CONFIG_MACF_SOCKET
125 int (*fsoreceive
)(struct socket
*so2
, struct sockaddr
**paddr
,
126 struct uio
*uio2
, struct mbuf
**mp0
, struct mbuf
**controlp
,
129 if ((so
= (struct socket
*)fp
->f_fglob
->fg_data
) == NULL
) {
130 /* This is not a valid open file descriptor */
134 #if CONFIG_MACF_SOCKET
135 error
= mac_socket_check_receive(vfs_context_ucred(ctx
), so
);
138 #endif /* CONFIG_MACF_SOCKET */
140 //###LD will have to change
141 fsoreceive
= so
->so_proto
->pr_usrreqs
->pru_soreceive
;
143 stat
= (*fsoreceive
)(so
, 0, uio
, 0, 0, 0);
149 soo_write(struct fileproc
*fp
, struct uio
*uio
, __unused
int flags
,
154 int (*fsosend
)(struct socket
*so2
, struct sockaddr
*addr
,
155 struct uio
*uio2
, struct mbuf
*top
, struct mbuf
*control
,
159 #if CONFIG_MACF_SOCKET
163 if ((so
= (struct socket
*)fp
->f_fglob
->fg_data
) == NULL
) {
164 /* This is not a valid open file descriptor */
168 #if CONFIG_MACF_SOCKET
169 /* JMM - have to fetch the socket's remote addr */
170 error
= mac_socket_check_send(vfs_context_ucred(ctx
), so
, NULL
);
173 #endif /* CONFIG_MACF_SOCKET */
175 fsosend
= so
->so_proto
->pr_usrreqs
->pru_sosend
;
177 stat
= (*fsosend
)(so
, 0, uio
, 0, 0, 0);
179 /* Generation of SIGPIPE can be controlled per socket */
180 procp
= vfs_context_proc(ctx
);
181 if (stat
== EPIPE
&& !(so
->so_flags
& SOF_NOSIGPIPE
))
182 psignal(procp
, SIGPIPE
);
187 __private_extern__
int
188 soioctl(struct socket
*so
, u_long cmd
, caddr_t data
, struct proc
*p
)
191 int dropsockref
= -1;
196 /* Call the socket filter's ioctl handler for most ioctls */
197 if (IOCGROUP(cmd
) != 'i' && IOCGROUP(cmd
) != 'r') {
198 error
= sflt_ioctl(so
, cmd
, data
);
205 case FIONBIO
: /* int */
206 bcopy(data
, &int_arg
, sizeof (int_arg
));
208 so
->so_state
|= SS_NBIO
;
210 so
->so_state
&= ~SS_NBIO
;
214 case FIOASYNC
: /* int */
215 bcopy(data
, &int_arg
, sizeof (int_arg
));
217 so
->so_state
|= SS_ASYNC
;
218 so
->so_rcv
.sb_flags
|= SB_ASYNC
;
219 so
->so_snd
.sb_flags
|= SB_ASYNC
;
221 so
->so_state
&= ~SS_ASYNC
;
222 so
->so_rcv
.sb_flags
&= ~SB_ASYNC
;
223 so
->so_snd
.sb_flags
&= ~SB_ASYNC
;
227 case FIONREAD
: /* int */
228 bcopy(&so
->so_rcv
.sb_cc
, data
, sizeof (u_int32_t
));
231 case SIOCSPGRP
: /* int */
232 bcopy(data
, &so
->so_pgid
, sizeof (pid_t
));
235 case SIOCGPGRP
: /* int */
236 bcopy(&so
->so_pgid
, data
, sizeof (pid_t
));
239 case SIOCATMARK
: /* int */
240 int_arg
= (so
->so_state
& SS_RCVATMARK
) != 0;
241 bcopy(&int_arg
, data
, sizeof (int_arg
));
244 case SIOCSETOT
: { /* int */
246 * Set socket level options here and then call protocol
249 struct socket
*cloned_so
= NULL
;
252 bcopy(data
, &cloned_fd
, sizeof (cloned_fd
));
254 /* let's make sure it's either -1 or a valid file descriptor */
255 if (cloned_fd
!= -1) {
256 error
= file_socket(cloned_fd
, &cloned_so
);
260 dropsockref
= cloned_fd
;
263 /* Always set socket non-blocking for OT */
264 so
->so_state
|= SS_NBIO
;
265 so
->so_options
|= SO_DONTTRUNC
| SO_WANTMORE
;
266 so
->so_flags
|= SOF_NOSIGPIPE
| SOF_NPX_SETOPTSHUT
;
268 if (cloned_so
&& so
!= cloned_so
) {
271 cloned_so
->so_options
& ~SO_ACCEPTCONN
;
274 if (so
->so_options
& SO_LINGER
)
275 so
->so_linger
= cloned_so
->so_linger
;
277 /* SO_SNDBUF, SO_RCVBUF */
278 if (cloned_so
->so_snd
.sb_hiwat
> 0) {
279 if (sbreserve(&so
->so_snd
,
280 cloned_so
->so_snd
.sb_hiwat
) == 0) {
285 if (cloned_so
->so_rcv
.sb_hiwat
> 0) {
286 if (sbreserve(&so
->so_rcv
,
287 cloned_so
->so_rcv
.sb_hiwat
) == 0) {
293 /* SO_SNDLOWAT, SO_RCVLOWAT */
294 so
->so_snd
.sb_lowat
=
295 (cloned_so
->so_snd
.sb_lowat
> so
->so_snd
.sb_hiwat
) ?
296 so
->so_snd
.sb_hiwat
: cloned_so
->so_snd
.sb_lowat
;
297 so
->so_rcv
.sb_lowat
=
298 (cloned_so
->so_rcv
.sb_lowat
> so
->so_rcv
.sb_hiwat
) ?
299 so
->so_rcv
.sb_hiwat
: cloned_so
->so_rcv
.sb_lowat
;
301 /* SO_SNDTIMEO, SO_RCVTIMEO */
302 so
->so_snd
.sb_timeo
= cloned_so
->so_snd
.sb_timeo
;
303 so
->so_rcv
.sb_timeo
= cloned_so
->so_rcv
.sb_timeo
;
306 error
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
, cmd
,
308 /* Just ignore protocols that do not understand it */
309 if (error
== EOPNOTSUPP
)
316 * Interface/routing/protocol specific ioctls:
317 * interface and routing ioctls should have a
318 * different entry since a socket's unnecessary
320 if (IOCGROUP(cmd
) == 'i') {
321 error
= ifioctllocked(so
, cmd
, data
, p
);
323 if (IOCGROUP(cmd
) == 'r')
324 error
= rtioctl(cmd
, data
, p
);
326 error
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
,
331 if (dropsockref
!= -1)
332 file_drop(dropsockref
);
333 socket_unlock(so
, 1);
335 if (error
== EJUSTRETURN
)
342 soo_ioctl(struct fileproc
*fp
, u_long cmd
, caddr_t data
, vfs_context_t ctx
)
346 proc_t procp
= vfs_context_proc(ctx
);
348 if ((so
= (struct socket
*)fp
->f_fglob
->fg_data
) == NULL
) {
349 /* This is not a valid open file descriptor */
353 error
= soioctl(so
, cmd
, data
, procp
);
355 if (error
== 0 && cmd
== SIOCSETOT
)
356 fp
->f_fglob
->fg_flag
|= FNONBLOCK
;
362 soo_select(struct fileproc
*fp
, int which
, void *wql
, vfs_context_t ctx
)
364 struct socket
*so
= (struct socket
*)fp
->f_fglob
->fg_data
;
368 if (so
== NULL
|| so
== (struct socket
*)-1)
371 procp
= vfs_context_proc(ctx
);
373 #if CONFIG_MACF_SOCKET
374 if (mac_socket_check_select(vfs_context_ucred(ctx
), so
, which
) != 0);
376 #endif /* CONFIG_MACF_SOCKET */
383 so
->so_rcv
.sb_flags
|= SB_SEL
;
384 if (soreadable(so
)) {
386 so
->so_rcv
.sb_flags
&= ~SB_SEL
;
389 selrecord(procp
, &so
->so_rcv
.sb_sel
, wql
);
393 so
->so_snd
.sb_flags
|= SB_SEL
;
394 if (sowriteable(so
)) {
396 so
->so_snd
.sb_flags
&= ~SB_SEL
;
399 selrecord(procp
, &so
->so_snd
.sb_sel
, wql
);
403 so
->so_rcv
.sb_flags
|= SB_SEL
;
404 if (so
->so_oobmark
|| (so
->so_state
& SS_RCVATMARK
)) {
406 so
->so_rcv
.sb_flags
&= ~SB_SEL
;
409 selrecord(procp
, &so
->so_rcv
.sb_sel
, wql
);
414 socket_unlock(so
, 1);
419 soo_stat(struct socket
*so
, void *ub
, int isstat64
)
422 /* warning avoidance ; protected by isstat64 */
423 struct stat
*sb
= (struct stat
*)0;
424 /* warning avoidance ; protected by isstat64 */
425 struct stat64
*sb64
= (struct stat64
*)0;
427 #if CONFIG_MACF_SOCKET
428 ret
= mac_socket_check_stat(kauth_cred_get(), so
);
434 sb64
= (struct stat64
*)ub
;
435 bzero((caddr_t
)sb64
, sizeof (*sb64
));
437 sb
= (struct stat
*)ub
;
438 bzero((caddr_t
)sb
, sizeof (*sb
));
443 sb64
->st_mode
= S_IFSOCK
;
444 if ((so
->so_state
& SS_CANTRCVMORE
) == 0 ||
445 so
->so_rcv
.sb_cc
!= 0)
446 sb64
->st_mode
|= S_IRUSR
| S_IRGRP
| S_IROTH
;
447 if ((so
->so_state
& SS_CANTSENDMORE
) == 0)
448 sb64
->st_mode
|= S_IWUSR
| S_IWGRP
| S_IWOTH
;
449 sb64
->st_size
= so
->so_rcv
.sb_cc
- so
->so_rcv
.sb_ctl
;
450 sb64
->st_uid
= kauth_cred_getuid(so
->so_cred
);
451 sb64
->st_gid
= kauth_cred_getgid(so
->so_cred
);
453 sb
->st_mode
= S_IFSOCK
;
454 if ((so
->so_state
& SS_CANTRCVMORE
) == 0 ||
455 so
->so_rcv
.sb_cc
!= 0)
456 sb
->st_mode
|= S_IRUSR
| S_IRGRP
| S_IROTH
;
457 if ((so
->so_state
& SS_CANTSENDMORE
) == 0)
458 sb
->st_mode
|= S_IWUSR
| S_IWGRP
| S_IWOTH
;
459 sb
->st_size
= so
->so_rcv
.sb_cc
- so
->so_rcv
.sb_ctl
;
460 sb
->st_uid
= kauth_cred_getuid(so
->so_cred
);
461 sb
->st_gid
= kauth_cred_getgid(so
->so_cred
);
464 ret
= (*so
->so_proto
->pr_usrreqs
->pru_sense
)(so
, ub
, isstat64
);
465 socket_unlock(so
, 1);
471 soo_close(struct fileglob
*fg
, __unused vfs_context_t ctx
)
476 sp
= (struct socket
*)fg
->fg_data
;
486 soo_drain(struct fileproc
*fp
, __unused vfs_context_t ctx
)
489 struct socket
*so
= (struct socket
*)fp
->f_fglob
->fg_data
;
493 so
->so_state
|= SS_DRAINING
;
495 wakeup((caddr_t
)&so
->so_timeo
);
498 soevent(so
, SO_FILT_HINT_LOCKED
);
500 socket_unlock(so
, 1);