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