]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/sys_socket.c
2 * Copyright (c) 2000 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>
60 #include <sys/protosw.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/filio.h> /* XXX */
64 #include <sys/sockio.h>
67 #include <sys/filedesc.h>
70 #include <net/route.h>
72 int soo_read
__P((struct file
*fp
, struct uio
*uio
,
74 int soo_write
__P((struct file
*fp
, struct uio
*uio
,
76 int soo_close
__P((struct file
*fp
, struct proc
*p
));
78 int soo_select
__P((struct file
*fp
, int which
, void * wql
, struct proc
*p
));
80 struct fileops socketops
=
81 { soo_read
, soo_write
, soo_ioctl
, soo_select
, soo_close
};
85 soo_read(fp
, uio
, cred
)
90 struct socket
*so
= (struct socket
*)fp
->f_data
;
93 int (*fsoreceive
) __P((struct socket
*so
,
94 struct sockaddr
**paddr
,
95 struct uio
*uio
, struct mbuf
**mp0
,
96 struct mbuf
**controlp
, int *flagsp
));
99 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
101 fsoreceive
= so
->so_proto
->pr_usrreqs
->pru_soreceive
;
102 if (fsoreceive
!= soreceive
)
103 { kp
= sotokextcb(so
);
105 { if (kp
->e_soif
&& kp
->e_soif
->sf_soreceive
)
106 (*kp
->e_soif
->sf_soreceive
)(so
, 0, &uio
,
113 stat
= (*fsoreceive
)(so
, 0, uio
, 0, 0, 0);
114 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
120 soo_write(fp
, uio
, cred
)
125 struct socket
*so
= (struct socket
*)fp
->f_data
;
126 int (*fsosend
) __P((struct socket
*so
, struct sockaddr
*addr
,
127 struct uio
*uio
, struct mbuf
*top
,
128 struct mbuf
*control
, int flags
));
132 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
133 fsosend
= so
->so_proto
->pr_usrreqs
->pru_sosend
;
134 if (fsosend
!= sosend
)
135 { kp
= sotokextcb(so
);
137 { if (kp
->e_soif
&& kp
->e_soif
->sf_sosend
)
138 (*kp
->e_soif
->sf_sosend
)(so
, 0, &uio
,
144 stat
= (*fsosend
)(so
, 0, uio
, 0, 0, 0);
145 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
150 soo_ioctl(fp
, cmd
, data
, p
)
153 register caddr_t data
;
156 register struct socket
*so
= (struct socket
*)fp
->f_data
;
162 sopt
.sopt_level
= cmd
;
163 sopt
.sopt_name
= (int)data
;
167 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
170 { if (kp
->e_soif
&& kp
->e_soif
->sf_socontrol
)
171 (*kp
->e_soif
->sf_socontrol
)(so
, &sopt
, kp
);
179 so
->so_state
|= SS_NBIO
;
181 so
->so_state
&= ~SS_NBIO
;
183 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
188 so
->so_state
|= SS_ASYNC
;
189 so
->so_rcv
.sb_flags
|= SB_ASYNC
;
190 so
->so_snd
.sb_flags
|= SB_ASYNC
;
192 so
->so_state
&= ~SS_ASYNC
;
193 so
->so_rcv
.sb_flags
&= ~SB_ASYNC
;
194 so
->so_snd
.sb_flags
&= ~SB_ASYNC
;
196 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
200 *(int *)data
= so
->so_rcv
.sb_cc
;
201 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
205 so
->so_pgid
= *(int *)data
;
206 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
210 *(int *)data
= so
->so_pgid
;
211 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
215 *(int *)data
= (so
->so_state
&SS_RCVATMARK
) != 0;
216 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
221 * Set socket level options here and then call protocol
224 struct socket
*cloned_so
= NULL
;
225 int cloned_fd
= *(int *)data
;
227 /* let's make sure it's either -1 or a valid file descriptor */
228 if (cloned_fd
!= -1) {
229 struct file
*cloned_fp
;
230 error
= getsock(p
->p_fd
, cloned_fd
, &cloned_fp
);
232 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
236 cloned_so
= (struct socket
*)cloned_fp
->f_data
;
239 /* Always set socket non-blocking for OT */
240 fp
->f_flag
|= FNONBLOCK
;
241 so
->so_state
|= SS_NBIO
;
242 so
->so_options
|= SO_DONTTRUNC
| SO_WANTMORE
;
244 if (cloned_so
&& so
!= cloned_so
) {
246 so
->so_options
|= cloned_so
->so_options
& ~SO_ACCEPTCONN
;
249 if (so
->so_options
& SO_LINGER
)
250 so
->so_linger
= cloned_so
->so_linger
;
252 /* SO_SNDBUF, SO_RCVBUF */
253 if (cloned_so
->so_snd
.sb_hiwat
> 0) {
254 if (sbreserve(&so
->so_snd
, cloned_so
->so_snd
.sb_hiwat
) == 0) {
256 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
260 if (cloned_so
->so_rcv
.sb_hiwat
> 0) {
261 if (sbreserve(&so
->so_rcv
, cloned_so
->so_rcv
.sb_hiwat
) == 0) {
263 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
268 /* SO_SNDLOWAT, SO_RCVLOWAT */
269 so
->so_snd
.sb_lowat
=
270 (cloned_so
->so_snd
.sb_lowat
> so
->so_snd
.sb_hiwat
) ?
271 so
->so_snd
.sb_hiwat
: cloned_so
->so_snd
.sb_lowat
;
272 so
->so_rcv
.sb_lowat
=
273 (cloned_so
->so_rcv
.sb_lowat
> so
->so_rcv
.sb_hiwat
) ?
274 so
->so_rcv
.sb_hiwat
: cloned_so
->so_rcv
.sb_lowat
;
276 /* SO_SNDTIMEO, SO_RCVTIMEO */
277 so
->so_snd
.sb_timeo
= cloned_so
->so_snd
.sb_timeo
;
278 so
->so_rcv
.sb_timeo
= cloned_so
->so_rcv
.sb_timeo
;
281 error
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
, cmd
, data
, 0, p
);
282 /* Just ignore protocols that do not understand it */
283 if (error
== EOPNOTSUPP
)
286 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
291 * Interface/routing/protocol specific ioctls:
292 * interface and routing ioctls should have a
293 * different entry since a socket's unnecessary
295 if (IOCGROUP(cmd
) == 'i')
296 error
= ifioctl(so
, cmd
, data
, p
);
298 if (IOCGROUP(cmd
) == 'r')
299 error
= rtioctl(cmd
, data
, p
);
301 error
= (*so
->so_proto
->pr_usrreqs
->pru_control
)(so
, cmd
, data
, 0, p
);
303 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
308 soo_select(fp
, which
, wql
, p
)
314 register struct socket
*so
= (struct socket
*)fp
->f_data
;
315 register int s
= splnet();
322 so
->so_rcv
.sb_flags
|= SB_SEL
;
323 if (soreadable(so
)) {
326 so
->so_rcv
.sb_flags
&= ~SB_SEL
;
329 selrecord(p
, &so
->so_rcv
.sb_sel
, wql
);
333 so
->so_snd
.sb_flags
|= SB_SEL
;
334 if (sowriteable(so
)) {
337 so
->so_snd
.sb_flags
&= ~SB_SEL
;
340 selrecord(p
, &so
->so_snd
.sb_sel
, wql
);
344 so
->so_rcv
.sb_flags
|= SB_SEL
;
345 if (so
->so_oobmark
|| (so
->so_state
& SS_RCVATMARK
)) {
348 so
->so_rcv
.sb_flags
&= ~SB_SEL
;
351 selrecord(p
, &so
->so_rcv
.sb_sel
, wql
);
362 register struct socket
*so
;
363 register struct stat
*ub
;
367 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
368 bzero((caddr_t
)ub
, sizeof (*ub
));
369 ub
->st_mode
= S_IFSOCK
;
370 stat
= (*so
->so_proto
->pr_usrreqs
->pru_sense
)(so
, ub
);
371 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
384 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
385 error
= soclose((struct socket
*)fp
->f_data
);
386 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);