]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/sys_socket.c
xnu-792.1.5.tar.gz
[apple/xnu.git] / bsd / kern / sys_socket.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
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>
59 #include <sys/file_internal.h>
60 #include <sys/event.h>
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>
69 #include <sys/kauth.h>
70 #include <sys/signalvar.h>
71
72 #include <net/if.h>
73 #include <net/route.h>
74
75 /*
76 * File operations on sockets.
77 */
78 int soo_read(struct fileproc *fp, struct uio *uio, kauth_cred_t cred,
79 int flags, struct proc *p);
80 int soo_write(struct fileproc *fp, struct uio *uio, kauth_cred_t cred,
81 int flags, struct proc *p);
82 int soo_close(struct fileglob *fp, struct proc *p);
83 int soo_ioctl(struct fileproc *fp, u_long cmd, caddr_t data, struct proc *p);
84 int soo_stat(struct socket *so, struct stat *ub);
85 int soo_select(struct fileproc *fp, int which, void * wql, struct proc *p);
86 int soo_kqfilter(struct fileproc *fp, struct knote *kn, struct proc *p);
87 int soo_drain(struct fileproc *fp, struct proc *p);
88
89 struct fileops socketops =
90 { soo_read, soo_write, soo_ioctl, soo_select, soo_close, soo_kqfilter, soo_drain };
91
92 /* ARGSUSED */
93 int
94 soo_read(
95 struct fileproc *fp,
96 struct uio *uio,
97 __unused kauth_cred_t cred,
98 __unused int flags,
99 __unused struct proc *p)
100 {
101 struct socket *so;
102 int stat;
103 int (*fsoreceive)(struct socket *so2,
104 struct sockaddr **paddr,
105 struct uio *uio2, struct mbuf **mp0,
106 struct mbuf **controlp, int *flagsp);
107
108
109
110 if ((so = (struct socket *)fp->f_fglob->fg_data) == NULL) {
111 /* This is not a valid open file descriptor */
112 return(EBADF);
113 }
114 //###LD will have to change
115 fsoreceive = so->so_proto->pr_usrreqs->pru_soreceive;
116
117 stat = (*fsoreceive)(so, 0, uio, 0, 0, 0);
118 return stat;
119 }
120
121 /* ARGSUSED */
122 int
123 soo_write(
124 struct fileproc *fp,
125 struct uio *uio,
126 __unused kauth_cred_t cred,
127 __unused int flags,
128 struct proc *procp)
129 {
130 struct socket *so;
131 int (*fsosend)(struct socket *so2, struct sockaddr *addr,
132 struct uio *uio2, struct mbuf *top,
133 struct mbuf *control, int flags2);
134 int stat;
135
136 if ((so = (struct socket *)fp->f_fglob->fg_data) == NULL) {
137 /* This is not a valid open file descriptor */
138 return (EBADF);
139 }
140
141 fsosend = so->so_proto->pr_usrreqs->pru_sosend;
142
143 stat = (*fsosend)(so, 0, uio, 0, 0, 0);
144
145 /* Generation of SIGPIPE can be controlled per socket */
146 if (stat == EPIPE && procp && !(so->so_flags & SOF_NOSIGPIPE))
147 psignal(procp, SIGPIPE);
148
149 return stat;
150 }
151
152 __private_extern__ int
153 soioctl(
154 struct socket *so,
155 u_long cmd,
156 caddr_t data,
157 struct proc *p)
158 {
159 struct sockopt sopt;
160 int error = 0;
161 int dropsockref = -1;
162
163
164 socket_lock(so, 1);
165
166 sopt.sopt_level = cmd;
167 sopt.sopt_name = (int)data;
168 sopt.sopt_p = p;
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
178 goto out;
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 }
190 goto out;
191
192 case FIONREAD:
193 *(int *)data = so->so_rcv.sb_cc;
194 goto out;
195
196 case SIOCSPGRP:
197 so->so_pgid = *(int *)data;
198 goto out;
199
200 case SIOCGPGRP:
201 *(int *)data = so->so_pgid;
202 goto out;
203
204 case SIOCATMARK:
205 *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
206 goto out;
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) {
218 error = file_socket(cloned_fd, &cloned_so);
219 if (error) {
220 goto out;
221 }
222 dropsockref = cloned_fd;
223 }
224
225 /* Always set socket non-blocking for OT */
226 so->so_state |= SS_NBIO;
227 so->so_options |= SO_DONTTRUNC | SO_WANTMORE;
228 so->so_flags |= SOF_NOSIGPIPE;
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;
242 goto out;
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;
248 goto out;
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
260 /* SO_SNDTIMEO, SO_RCVTIMEO */
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
270 goto out;
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')
279 error = ifioctllocked(so, cmd, data, p);
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
286 out:
287 if (dropsockref != -1)
288 file_drop(dropsockref);
289 socket_unlock(so, 1);
290
291 return error;
292 }
293
294 int
295 soo_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
315 return error;
316 }
317
318 int
319 soo_select(fp, which, wql, p)
320 struct fileproc *fp;
321 int which;
322 void * wql;
323 struct proc *p;
324 {
325 register struct socket *so = (struct socket *)fp->f_fglob->fg_data;
326 int retnum=0;
327
328 if (so == NULL || so == (struct socket*)-1)
329 return (0);
330
331 socket_lock(so, 1);
332 switch (which) {
333
334 case FREAD:
335 so->so_rcv.sb_flags |= SB_SEL;
336 if (soreadable(so)) {
337 retnum = 1;
338 so->so_rcv.sb_flags &= ~SB_SEL;
339 goto done;
340 }
341 selrecord(p, &so->so_rcv.sb_sel, wql);
342 break;
343
344 case FWRITE:
345 so->so_snd.sb_flags |= SB_SEL;
346 if (sowriteable(so)) {
347 retnum = 1;
348 so->so_snd.sb_flags &= ~SB_SEL;
349 goto done;
350 }
351 selrecord(p, &so->so_snd.sb_sel, wql);
352 break;
353
354 case 0:
355 so->so_rcv.sb_flags |= SB_SEL;
356 if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
357 retnum = 1;
358 so->so_rcv.sb_flags &= ~SB_SEL;
359 goto done;
360 }
361 selrecord(p, &so->so_rcv.sb_sel, wql);
362 break;
363 }
364
365 done:
366 socket_unlock(so, 1);
367 return (retnum);
368 }
369
370
371 int
372 soo_stat(so, ub)
373 register struct socket *so;
374 register struct stat *ub;
375 {
376 int stat;
377
378 bzero((caddr_t)ub, sizeof (*ub));
379 socket_lock(so, 1);
380 ub->st_mode = S_IFSOCK;
381 stat = (*so->so_proto->pr_usrreqs->pru_sense)(so, ub);
382 socket_unlock(so, 1);
383 return stat;
384 }
385
386 /* ARGSUSED */
387 int
388 soo_close(struct fileglob *fg, __unused proc_t p)
389 {
390 int error = 0;
391 struct socket *sp;
392
393 sp = (struct socket *)fg->fg_data;
394 fg->fg_data = NULL;
395
396
397 if (sp)
398 error = soclose(sp);
399
400
401 return (error);
402 }
403
404 int
405 soo_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