]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/sys_socket.c
xnu-792.tar.gz
[apple/xnu.git] / bsd / kern / sys_socket.c
CommitLineData
1c79356b 1/*
9bccf70c 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
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.
1c79356b 11 *
e5568f75
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1982, 1986, 1990, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
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.
41 *
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
52 * SUCH DAMAGE.
53 *
54 * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93
55 */
56
57#include <sys/param.h>
58#include <sys/systm.h>
91447636 59#include <sys/file_internal.h>
55e303ae 60#include <sys/event.h>
1c79356b
A
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>
66#include <sys/stat.h>
67#include <sys/uio.h>
68#include <sys/filedesc.h>
91447636
A
69#include <sys/kauth.h>
70#include <sys/signalvar.h>
1c79356b
A
71
72#include <net/if.h>
73#include <net/route.h>
74
91447636
A
75/*
76 * File operations on sockets.
77 */
78int soo_read(struct fileproc *fp, struct uio *uio, kauth_cred_t cred,
79 int flags, struct proc *p);
80int soo_write(struct fileproc *fp, struct uio *uio, kauth_cred_t cred,
81 int flags, struct proc *p);
82int soo_close(struct fileglob *fp, struct proc *p);
83int soo_ioctl(struct fileproc *fp, u_long cmd, caddr_t data, struct proc *p);
84int soo_stat(struct socket *so, struct stat *ub);
85int soo_select(struct fileproc *fp, int which, void * wql, struct proc *p);
86int soo_kqfilter(struct fileproc *fp, struct knote *kn, struct proc *p);
87int soo_drain(struct fileproc *fp, struct proc *p);
55e303ae 88
1c79356b 89struct fileops socketops =
91447636 90 { soo_read, soo_write, soo_ioctl, soo_select, soo_close, soo_kqfilter, soo_drain };
1c79356b
A
91
92/* ARGSUSED */
93int
91447636
A
94soo_read(
95 struct fileproc *fp,
96 struct uio *uio,
97 __unused kauth_cred_t cred,
98 __unused int flags,
99 __unused struct proc *p)
1c79356b 100{
9bccf70c 101 struct socket *so;
1c79356b 102 int stat;
91447636 103 int (*fsoreceive)(struct socket *so2,
1c79356b 104 struct sockaddr **paddr,
91447636
A
105 struct uio *uio2, struct mbuf **mp0,
106 struct mbuf **controlp, int *flagsp);
1c79356b 107
0b4e3aa0 108
0b4e3aa0 109
91447636 110 if ((so = (struct socket *)fp->f_fglob->fg_data) == NULL) {
9bccf70c 111 /* This is not a valid open file descriptor */
91447636 112 return(EBADF);
9bccf70c 113 }
91447636 114//###LD will have to change
1c79356b 115 fsoreceive = so->so_proto->pr_usrreqs->pru_soreceive;
1c79356b
A
116
117 stat = (*fsoreceive)(so, 0, uio, 0, 0, 0);
1c79356b
A
118 return stat;
119}
120
121/* ARGSUSED */
122int
91447636
A
123soo_write(
124 struct fileproc *fp,
125 struct uio *uio,
126 __unused kauth_cred_t cred,
127 __unused int flags,
128 struct proc *procp)
1c79356b 129{
9bccf70c 130 struct socket *so;
91447636
A
131 int (*fsosend)(struct socket *so2, struct sockaddr *addr,
132 struct uio *uio2, struct mbuf *top,
133 struct mbuf *control, int flags2);
1c79356b
A
134 int stat;
135
91447636
A
136 if ((so = (struct socket *)fp->f_fglob->fg_data) == NULL) {
137 /* This is not a valid open file descriptor */
138 return (EBADF);
139 }
9bccf70c 140
1c79356b 141 fsosend = so->so_proto->pr_usrreqs->pru_sosend;
1c79356b
A
142
143 stat = (*fsosend)(so, 0, uio, 0, 0, 0);
9bccf70c 144
91447636
A
145 /* Generation of SIGPIPE can be controlled per socket */
146 if (stat == EPIPE && procp && !(so->so_flags & SOF_NOSIGPIPE))
147 psignal(procp, SIGPIPE);
9bccf70c 148
91447636 149 return stat;
1c79356b
A
150}
151
91447636
A
152__private_extern__ int
153soioctl(
154 struct socket *so,
155 u_long cmd,
156 caddr_t data,
157 struct proc *p)
1c79356b 158{
1c79356b 159 struct sockopt sopt;
1c79356b 160 int error = 0;
91447636 161 int dropsockref = -1;
1c79356b 162
9bccf70c 163
91447636 164 socket_lock(so, 1);
9bccf70c 165
91447636
A
166 sopt.sopt_level = cmd;
167 sopt.sopt_name = (int)data;
168 sopt.sopt_p = p;
1c79356b
A
169
170 switch (cmd) {
171
172 case FIONBIO:
173 if (*(int *)data)
174 so->so_state |= SS_NBIO;
175 else
176 so->so_state &= ~SS_NBIO;
177
91447636 178 goto out;
1c79356b
A
179
180 case FIOASYNC:
181 if (*(int *)data) {
182 so->so_state |= SS_ASYNC;
183 so->so_rcv.sb_flags |= SB_ASYNC;
184 so->so_snd.sb_flags |= SB_ASYNC;
185 } else {
186 so->so_state &= ~SS_ASYNC;
187 so->so_rcv.sb_flags &= ~SB_ASYNC;
188 so->so_snd.sb_flags &= ~SB_ASYNC;
189 }
91447636 190 goto out;
1c79356b
A
191
192 case FIONREAD:
193 *(int *)data = so->so_rcv.sb_cc;
91447636 194 goto out;
1c79356b
A
195
196 case SIOCSPGRP:
197 so->so_pgid = *(int *)data;
91447636 198 goto out;
1c79356b
A
199
200 case SIOCGPGRP:
201 *(int *)data = so->so_pgid;
91447636 202 goto out;
1c79356b
A
203
204 case SIOCATMARK:
205 *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
91447636 206 goto out;
1c79356b
A
207
208 case SIOCSETOT: {
209 /*
210 * Set socket level options here and then call protocol
211 * specific routine.
212 */
213 struct socket *cloned_so = NULL;
214 int cloned_fd = *(int *)data;
215
216 /* let's make sure it's either -1 or a valid file descriptor */
217 if (cloned_fd != -1) {
91447636 218 error = file_socket(cloned_fd, &cloned_so);
1c79356b 219 if (error) {
91447636 220 goto out;
1c79356b 221 }
91447636 222 dropsockref = cloned_fd;
1c79356b
A
223 }
224
225 /* Always set socket non-blocking for OT */
1c79356b
A
226 so->so_state |= SS_NBIO;
227 so->so_options |= SO_DONTTRUNC | SO_WANTMORE;
9bccf70c 228 so->so_flags |= SOF_NOSIGPIPE;
1c79356b
A
229
230 if (cloned_so && so != cloned_so) {
231 /* Flags options */
232 so->so_options |= cloned_so->so_options & ~SO_ACCEPTCONN;
233
234 /* SO_LINGER */
235 if (so->so_options & SO_LINGER)
236 so->so_linger = cloned_so->so_linger;
237
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) {
241 error = ENOBUFS;
91447636 242 goto out;
1c79356b
A
243 }
244 }
245 if (cloned_so->so_rcv.sb_hiwat > 0) {
246 if (sbreserve(&so->so_rcv, cloned_so->so_rcv.sb_hiwat) == 0) {
247 error = ENOBUFS;
91447636 248 goto out;
1c79356b
A
249 }
250 }
251
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;
259
91447636 260 /* SO_SNDTIMEO, SO_RCVTIMEO */
1c79356b
A
261 so->so_snd.sb_timeo = cloned_so->so_snd.sb_timeo;
262 so->so_rcv.sb_timeo = cloned_so->so_rcv.sb_timeo;
263 }
264
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)
268 error = 0;
269
91447636 270 goto out;
1c79356b
A
271 }
272 }
273 /*
274 * Interface/routing/protocol specific ioctls:
275 * interface and routing ioctls should have a
276 * different entry since a socket's unnecessary
277 */
278 if (IOCGROUP(cmd) == 'i')
91447636 279 error = ifioctllocked(so, cmd, data, p);
1c79356b
A
280 else
281 if (IOCGROUP(cmd) == 'r')
282 error = rtioctl(cmd, data, p);
283 else
284 error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p);
285
91447636
A
286out:
287 if (dropsockref != -1)
288 file_drop(dropsockref);
289 socket_unlock(so, 1);
290
291 return error;
292}
293
294int
295soo_ioctl(fp, cmd, data, p)
296 struct fileproc *fp;
297 u_long cmd;
298 register caddr_t data;
299 struct proc *p;
300{
301 register struct socket *so;
302 int error;
303
304
305 if ((so = (struct socket *)fp->f_fglob->fg_data) == NULL) {
306 /* This is not a valid open file descriptor */
307 return (EBADF);
308 }
309
310 error = soioctl(so, cmd, data, p);
311
312 if (error == 0 && cmd == SIOCSETOT)
313 fp->f_fglob->fg_flag |= FNONBLOCK;
314
1c79356b
A
315 return error;
316}
317
318int
0b4e3aa0 319soo_select(fp, which, wql, p)
91447636 320 struct fileproc *fp;
1c79356b 321 int which;
0b4e3aa0 322 void * wql;
1c79356b
A
323 struct proc *p;
324{
91447636 325 register struct socket *so = (struct socket *)fp->f_fglob->fg_data;
1c79356b
A
326 int retnum=0;
327
91447636
A
328 if (so == NULL || so == (struct socket*)-1)
329 return (0);
1c79356b 330
91447636 331 socket_lock(so, 1);
1c79356b
A
332 switch (which) {
333
334 case FREAD:
0b4e3aa0 335 so->so_rcv.sb_flags |= SB_SEL;
1c79356b 336 if (soreadable(so)) {
1c79356b 337 retnum = 1;
0b4e3aa0 338 so->so_rcv.sb_flags &= ~SB_SEL;
1c79356b
A
339 goto done;
340 }
0b4e3aa0 341 selrecord(p, &so->so_rcv.sb_sel, wql);
1c79356b
A
342 break;
343
344 case FWRITE:
0b4e3aa0 345 so->so_snd.sb_flags |= SB_SEL;
1c79356b 346 if (sowriteable(so)) {
1c79356b 347 retnum = 1;
0b4e3aa0 348 so->so_snd.sb_flags &= ~SB_SEL;
1c79356b
A
349 goto done;
350 }
0b4e3aa0 351 selrecord(p, &so->so_snd.sb_sel, wql);
1c79356b
A
352 break;
353
354 case 0:
0b4e3aa0 355 so->so_rcv.sb_flags |= SB_SEL;
1c79356b 356 if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
1c79356b 357 retnum = 1;
0b4e3aa0 358 so->so_rcv.sb_flags &= ~SB_SEL;
1c79356b
A
359 goto done;
360 }
0b4e3aa0 361 selrecord(p, &so->so_rcv.sb_sel, wql);
1c79356b
A
362 break;
363 }
91447636 364
1c79356b 365done:
91447636 366 socket_unlock(so, 1);
1c79356b
A
367 return (retnum);
368}
369
370
371int
372soo_stat(so, ub)
373 register struct socket *so;
374 register struct stat *ub;
375{
9bccf70c 376 int stat;
1c79356b 377
1c79356b 378 bzero((caddr_t)ub, sizeof (*ub));
91447636 379 socket_lock(so, 1);
1c79356b
A
380 ub->st_mode = S_IFSOCK;
381 stat = (*so->so_proto->pr_usrreqs->pru_sense)(so, ub);
91447636 382 socket_unlock(so, 1);
1c79356b
A
383 return stat;
384}
385
386/* ARGSUSED */
387int
91447636 388soo_close(struct fileglob *fg, __unused proc_t p)
1c79356b
A
389{
390 int error = 0;
55e303ae
A
391 struct socket *sp;
392
91447636
A
393 sp = (struct socket *)fg->fg_data;
394 fg->fg_data = NULL;
1c79356b 395
9bccf70c 396
55e303ae
A
397 if (sp)
398 error = soclose(sp);
9bccf70c 399
1c79356b 400
1c79356b
A
401 return (error);
402}
91447636
A
403
404int
405soo_drain(struct fileproc *fp, __unused struct proc *p)
406{
407 int error = 0;
408 struct socket *so = (struct socket *)fp->f_fglob->fg_data;
409
410 if (so) {
411 socket_lock(so, 1);
412 so->so_state |= SS_DRAINING;
413
414 wakeup((caddr_t)&so->so_timeo);
415 sorwakeup(so);
416 sowwakeup(so);
417
418 socket_unlock(so, 1);
419 }
420
421 return error;
422}
423