]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/uipc_syscalls.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / kern / uipc_syscalls.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
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.
8f6c56a5 11 *
6601e61a
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
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
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.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/*
23 * Copyright (c) 1982, 1986, 1989, 1990, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * sendfile(2) and related extensions:
27 * Copyright (c) 1998, David Greenman. All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
58 */
59
60
61
62#include <sys/param.h>
63#include <sys/systm.h>
64#include <sys/filedesc.h>
91447636
A
65#include <sys/proc_internal.h>
66#include <sys/file_internal.h>
1c79356b
A
67#include <sys/malloc.h>
68#include <sys/mbuf.h>
91447636
A
69#include <kern/lock.h>
70#include <sys/domain.h>
1c79356b 71#include <sys/protosw.h>
91447636 72#include <sys/signalvar.h>
1c79356b
A
73#include <sys/socket.h>
74#include <sys/socketvar.h>
75#if KTRACE
76#include <sys/ktrace.h>
77#endif
78#include <sys/kernel.h>
91447636 79#include <sys/uio_internal.h>
e5568f75
A
80
81#include <bsm/audit_kernel.h>
1c79356b
A
82
83#include <sys/kdebug.h>
91447636
A
84#include <sys/sysproto.h>
85
86#define f_flag f_fglob->fg_flag
87#define f_type f_fglob->fg_type
88#define f_msgcount f_fglob->fg_msgcount
89#define f_cred f_fglob->fg_cred
90#define f_ops f_fglob->fg_ops
91#define f_offset f_fglob->fg_offset
92#define f_data f_fglob->fg_data
1c79356b
A
93#if KDEBUG
94
95#define DBG_LAYER_IN_BEG NETDBG_CODE(DBG_NETSOCK, 0)
96#define DBG_LAYER_IN_END NETDBG_CODE(DBG_NETSOCK, 2)
97#define DBG_LAYER_OUT_BEG NETDBG_CODE(DBG_NETSOCK, 1)
98#define DBG_LAYER_OUT_END NETDBG_CODE(DBG_NETSOCK, 3)
99#define DBG_FNC_SENDMSG NETDBG_CODE(DBG_NETSOCK, (1 << 8) | 1)
100#define DBG_FNC_SENDTO NETDBG_CODE(DBG_NETSOCK, (2 << 8) | 1)
101#define DBG_FNC_SENDIT NETDBG_CODE(DBG_NETSOCK, (3 << 8) | 1)
102#define DBG_FNC_RECVFROM NETDBG_CODE(DBG_NETSOCK, (5 << 8))
103#define DBG_FNC_RECVMSG NETDBG_CODE(DBG_NETSOCK, (6 << 8))
104#define DBG_FNC_RECVIT NETDBG_CODE(DBG_NETSOCK, (7 << 8))
105
106#endif
107
1c79356b 108
91447636
A
109#define HACK_FOR_4056224 1
110#if HACK_FOR_4056224
111static pid_t last_pid_4056224 = 0;
112#endif /* HACK_FOR_4056224 */
1c79356b
A
113
114
1c79356b
A
115#if SENDFILE
116static void sf_buf_init(void *arg);
117SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL)
118static struct sf_buf *sf_buf_alloc(void);
119static void sf_buf_ref(caddr_t addr, u_int size);
120static void sf_buf_free(caddr_t addr, u_int size);
121
122static SLIST_HEAD(, sf_buf) sf_freelist;
123static vm_offset_t sf_base;
124static struct sf_buf *sf_bufs;
125static int sf_buf_alloc_want;
126#endif
127
91447636
A
128static int sendit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
129 int flags, register_t *retval);
130static int recvit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
131 user_addr_t namelenp, register_t *retval);
1c79356b 132
91447636
A
133static int accept1(struct proc *p, struct accept_args *uap, register_t *retval, int compat);
134static int getsockname1(struct proc *p, struct getsockname_args *uap,
135 register_t *retval, int compat);
136static int getpeername1(struct proc *p, struct getpeername_args *uap,
137 register_t *retval, int compat);
138
139
140#if COMPAT_43_SOCKET
141struct orecvmsg_args {
142 int s;
143 struct omsghdr *msg;
144 int flags;
145};
146struct osendmsg_args {
147 int s;
148 caddr_t msg;
149 int flags;
150};
151struct osend_args {
152 int s;
153 caddr_t buf;
154 int len;
155 int flags;
156};
157struct orecv_args {
158 int s;
159 caddr_t buf;
160 int len;
161 int flags;
162};
163
164int oaccept(struct proc *p, struct accept_args *uap, register_t *retval);
165int ogetpeername(struct proc *p, struct getpeername_args *uap, register_t *retval);
166int ogetsockname(struct proc *p, struct getsockname_args *uap, register_t *retval);
167int orecv(struct proc *p, struct orecv_args *uap, register_t *retval);
168int orecvfrom(struct proc *p, struct recvfrom_args *uap, register_t *retval);
169int orecvmsg(struct proc *p, struct orecvmsg_args *uap, register_t *retval);
170int osend(struct proc *p, struct osend_args *uap, register_t *retval);
171int osendmsg(struct proc *p, struct osendmsg_args *uap, register_t *retval);
172#endif // COMPAT_43_SOCKET
1c79356b
A
173
174/*
175 * System call interface to the socket abstraction.
176 */
1c79356b
A
177
178extern struct fileops socketops;
179
1c79356b
A
180int
181socket(p, uap, retval)
182 struct proc *p;
183 register struct socket_args *uap;
184 register_t *retval;
185{
1c79356b 186 struct socket *so;
91447636 187 struct fileproc *fp;
1c79356b
A
188 int fd, error;
189
55e303ae 190 AUDIT_ARG(socket, uap->domain, uap->type, uap->protocol);
1c79356b 191
91447636
A
192 error = falloc(p, &fp, &fd);
193 if (error) {
1c79356b 194 return (error);
91447636 195 }
1c79356b
A
196 fp->f_flag = FREAD|FWRITE;
197 fp->f_type = DTYPE_SOCKET;
198 fp->f_ops = &socketops;
91447636
A
199
200 error = socreate(uap->domain, &so, uap->type, uap->protocol);
201 if (error) {
202 fp_free(p, fd, fp);
1c79356b
A
203 } else {
204 fp->f_data = (caddr_t)so;
91447636
A
205
206 proc_fdlock(p);
6601e61a 207 procfdtbl_releasefd(p, fd, NULL);
91447636
A
208
209 fp_drop(p, fd, fp, 1);
210 proc_fdunlock(p);
211
1c79356b
A
212 *retval = fd;
213 }
214 return (error);
215}
216
1c79356b
A
217/* ARGSUSED */
218int
91447636 219bind(struct proc *p, struct bind_args *uap, __unused register_t *retval)
1c79356b 220{
1c79356b 221 struct sockaddr *sa;
91447636 222 struct socket *so;
1c79356b
A
223 int error;
224
55e303ae 225 AUDIT_ARG(fd, uap->s);
91447636 226 error = file_socket(uap->s, &so);
1c79356b
A
227 if (error)
228 return (error);
229 error = getsockaddr(&sa, uap->name, uap->namelen);
91447636
A
230 if (error)
231 goto out;
55e303ae 232 AUDIT_ARG(sockaddr, p, sa);
91447636
A
233 if (so != NULL)
234 error = sobind(so, sa);
55e303ae
A
235 else
236 error = EBADF;
1c79356b 237 FREE(sa, M_SONAME);
91447636
A
238out:
239 file_drop(uap->s);
1c79356b
A
240 return (error);
241}
242
1c79356b
A
243
244int
91447636
A
245listen(__unused struct proc *p, register struct listen_args *uap,
246 __unused register_t *retval)
1c79356b 247{
1c79356b 248 int error;
91447636 249 struct socket * so;
1c79356b 250
55e303ae 251 AUDIT_ARG(fd, uap->s);
91447636 252 error = file_socket(uap->s, &so);
1c79356b
A
253 if (error)
254 return (error);
91447636
A
255 if (so != NULL)
256 error = solisten(so, uap->backlog);
55e303ae 257 else
91447636
A
258 error = EBADF;
259 file_drop(uap->s);
260 return (error);
1c79356b
A
261}
262
91447636 263#if !COMPAT_43_SOCKET
1c79356b
A
264#define accept1 accept
265#endif
266
267
268
269int
91447636 270accept1(struct proc *p, struct accept_args *uap, register_t *retval, int compat)
1c79356b 271{
91447636 272 struct fileproc *fp;
1c79356b 273 struct sockaddr *sa;
91447636
A
274 socklen_t namelen;
275 int error;
276 struct socket *head, *so = NULL;
277 lck_mtx_t *mutex_held;
278 int fd = uap->s;
279 int newfd;;
1c79356b 280 short fflag; /* type must match fp->f_flag */
91447636 281 int dosocklock = 0;
1c79356b 282
55e303ae 283 AUDIT_ARG(fd, uap->s);
1c79356b 284 if (uap->name) {
91447636
A
285 error = copyin(uap->anamelen, (caddr_t)&namelen,
286 sizeof(socklen_t));
1c79356b
A
287 if(error)
288 return (error);
289 }
91447636
A
290 error = fp_getfsock(p, fd, &fp, &head);
291 if (error) {
292 if (error == EOPNOTSUPP)
293 error = ENOTSOCK;
1c79356b 294 return (error);
91447636 295 }
55e303ae 296 if (head == NULL) {
91447636
A
297 error = EBADF;
298 goto out;
55e303ae 299 }
91447636
A
300
301 socket_lock(head, 1);
302
303 if (head->so_proto->pr_getlock != NULL) {
304 mutex_held = (*head->so_proto->pr_getlock)(head, 0);
305 dosocklock = 1;
306 }
307 else {
308 mutex_held = head->so_proto->pr_domain->dom_mtx;
309 dosocklock = 0;
310 }
311
312
1c79356b 313 if ((head->so_options & SO_ACCEPTCONN) == 0) {
91447636
A
314 socket_unlock(head, 1);
315 error = EINVAL;
316 goto out;
1c79356b
A
317 }
318 if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) {
91447636
A
319 socket_unlock(head, 1);
320 error = EWOULDBLOCK;
321 goto out;
1c79356b 322 }
e3027f41 323 while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
1c79356b
A
324 if (head->so_state & SS_CANTRCVMORE) {
325 head->so_error = ECONNABORTED;
326 break;
327 }
91447636
A
328 if (head->so_usecount < 1)
329 panic("accept1: head=%x refcount=%d\n", head, head->so_usecount);
330 error = msleep((caddr_t)&head->so_timeo, mutex_held, PSOCK | PCATCH,
1c79356b 331 "accept", 0);
91447636
A
332 if (head->so_usecount < 1)
333 panic("accept1: 2 head=%x refcount=%d\n", head, head->so_usecount);
334 if ((head->so_state & SS_DRAINING)) {
335 error = ECONNABORTED;
336 }
1c79356b 337 if (error) {
91447636
A
338 socket_unlock(head, 1);
339 goto out;
1c79356b
A
340 }
341 }
342 if (head->so_error) {
343 error = head->so_error;
344 head->so_error = 0;
91447636
A
345 socket_unlock(head, 1);
346 goto out;
1c79356b
A
347 }
348
349
350 /*
351 * At this point we know that there is at least one connection
352 * ready to be accepted. Remove it from the queue prior to
353 * allocating the file descriptor for it since falloc() may
354 * block allowing another process to accept the connection
355 * instead.
356 */
91447636 357 lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
e3027f41 358 so = TAILQ_FIRST(&head->so_comp);
1c79356b
A
359 TAILQ_REMOVE(&head->so_comp, so, so_list);
360 head->so_qlen--;
91447636 361 socket_unlock(head, 0); /* unlock head to avoid deadlock with select, keep a ref on head */
1c79356b 362 fflag = fp->f_flag;
91447636
A
363 proc_fdlock(p);
364 error = falloc_locked(p, &fp, &newfd, 1);
1c79356b
A
365 if (error) {
366 /*
367 * Probably ran out of file descriptors. Put the
368 * unaccepted connection back onto the queue and
369 * do another wakeup so some other process might
370 * have a chance at it.
371 */
91447636
A
372 proc_fdunlock(p);
373 socket_lock(head, 0);
1c79356b
A
374 TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
375 head->so_qlen++;
91447636
A
376 wakeup_one((caddr_t)&head->so_timeo);
377 socket_unlock(head, 1);
378 goto out;
379 }
6601e61a 380 procfdtbl_releasefd(p, newfd, NULL);
91447636 381 *retval = newfd;
1c79356b
A
382 fp->f_type = DTYPE_SOCKET;
383 fp->f_flag = fflag;
384 fp->f_ops = &socketops;
385 fp->f_data = (caddr_t)so;
91447636
A
386 fp_drop(p, newfd, fp, 1);
387 proc_fdunlock(p);
388 socket_lock(head, 0);
389 if (dosocklock)
390 socket_lock(so, 1);
391 so->so_state &= ~SS_COMP;
392 so->so_head = NULL;
1c79356b 393 sa = 0;
91447636
A
394 (void) soacceptlock(so, &sa, 0);
395 socket_unlock(head, 1);
1c79356b
A
396 if (sa == 0) {
397 namelen = 0;
398 if (uap->name)
399 goto gotnoname;
91447636
A
400 if (dosocklock)
401 socket_unlock(so, 1);
402 error = 0;
403 goto out;
1c79356b 404 }
55e303ae 405 AUDIT_ARG(sockaddr, p, sa);
1c79356b
A
406 if (uap->name) {
407 /* check sa_len before it is destroyed */
408 if (namelen > sa->sa_len)
409 namelen = sa->sa_len;
91447636 410#if COMPAT_43_SOCKET
1c79356b
A
411 if (compat)
412 ((struct osockaddr *)sa)->sa_family =
413 sa->sa_family;
414#endif
91447636 415 error = copyout(sa, uap->name, namelen);
1c79356b
A
416 if (!error)
417gotnoname:
91447636
A
418 error = copyout((caddr_t)&namelen, uap->anamelen,
419 sizeof(socklen_t));
1c79356b
A
420 }
421 FREE(sa, M_SONAME);
91447636
A
422 if (dosocklock)
423 socket_unlock(so, 1);
424out:
425 file_drop(fd);
1c79356b
A
426 return (error);
427}
428
429int
91447636 430accept(struct proc *p, struct accept_args *uap, register_t *retval)
1c79356b
A
431{
432
433 return (accept1(p, uap, retval, 0));
434}
435
91447636 436#if COMPAT_43_SOCKET
1c79356b 437int
91447636 438oaccept(struct proc *p, struct accept_args *uap, register_t *retval)
1c79356b
A
439{
440
441 return (accept1(p, uap, retval, 1));
442}
91447636 443#endif /* COMPAT_43_SOCKET */
1c79356b 444
1c79356b
A
445/* ARGSUSED */
446int
91447636 447connect(struct proc *p, struct connect_args *uap, __unused register_t *retval)
1c79356b 448{
91447636 449 struct socket *so;
1c79356b 450 struct sockaddr *sa;
91447636
A
451 lck_mtx_t *mutex_held;
452 int error;
453 int fd = uap->s;
1c79356b 454
55e303ae 455 AUDIT_ARG(fd, uap->s);
91447636 456 error = file_socket( fd, &so);
1c79356b
A
457 if (error)
458 return (error);
91447636
A
459 if (so == NULL) {
460 error = EBADF;
461 goto out;
462 }
463
464 socket_lock(so, 1);
465
466 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
467 socket_unlock(so, 1);
468 error = EALREADY;
469 goto out;
470 }
1c79356b 471 error = getsockaddr(&sa, uap->name, uap->namelen);
91447636
A
472 if (error) {
473 socket_unlock(so, 1);
474 goto out;
475 }
55e303ae 476 AUDIT_ARG(sockaddr, p, sa);
91447636 477 error = soconnectlock(so, sa, 0);
1c79356b
A
478 if (error)
479 goto bad;
480 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
481 FREE(sa, M_SONAME);
91447636
A
482 socket_unlock(so, 1);
483 error = EINPROGRESS;
484 goto out;
1c79356b 485 }
1c79356b 486 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
91447636
A
487 if (so->so_proto->pr_getlock != NULL)
488 mutex_held = (*so->so_proto->pr_getlock)(so, 0);
489 else
490 mutex_held = so->so_proto->pr_domain->dom_mtx;
491 error = msleep((caddr_t)&so->so_timeo, mutex_held, PSOCK | PCATCH,
1c79356b 492 "connec", 0);
91447636
A
493 if ((so->so_state & SS_DRAINING)) {
494 error = ECONNABORTED;
495 }
1c79356b
A
496 if (error)
497 break;
498 }
499 if (error == 0) {
500 error = so->so_error;
501 so->so_error = 0;
502 }
1c79356b
A
503bad:
504 so->so_state &= ~SS_ISCONNECTING;
91447636 505 socket_unlock(so, 1);
1c79356b
A
506 FREE(sa, M_SONAME);
507 if (error == ERESTART)
508 error = EINTR;
91447636
A
509out:
510 file_drop(fd);
1c79356b
A
511 return (error);
512}
513
1c79356b 514int
91447636 515socketpair(struct proc *p, struct socketpair_args *uap, __unused register_t *retval)
1c79356b 516{
91447636 517 struct fileproc *fp1, *fp2;
1c79356b
A
518 struct socket *so1, *so2;
519 int fd, error, sv[2];
520
55e303ae 521 AUDIT_ARG(socket, uap->domain, uap->type, uap->protocol);
1c79356b
A
522 error = socreate(uap->domain, &so1, uap->type, uap->protocol);
523 if (error)
524 return (error);
525 error = socreate(uap->domain, &so2, uap->type, uap->protocol);
526 if (error)
527 goto free1;
91447636 528
1c79356b 529 error = falloc(p, &fp1, &fd);
91447636 530 if (error) {
1c79356b 531 goto free2;
91447636 532 }
1c79356b
A
533 fp1->f_flag = FREAD|FWRITE;
534 fp1->f_type = DTYPE_SOCKET;
535 fp1->f_ops = &socketops;
536 fp1->f_data = (caddr_t)so1;
91447636
A
537 sv[0] = fd;
538
1c79356b 539 error = falloc(p, &fp2, &fd);
91447636 540 if (error) {
1c79356b 541 goto free3;
91447636 542 }
1c79356b
A
543 fp2->f_flag = FREAD|FWRITE;
544 fp2->f_type = DTYPE_SOCKET;
545 fp2->f_ops = &socketops;
546 fp2->f_data = (caddr_t)so2;
547 sv[1] = fd;
91447636 548
1c79356b
A
549 error = soconnect2(so1, so2);
550 if (error) {
1c79356b
A
551 goto free4;
552 }
1c79356b
A
553 if (uap->type == SOCK_DGRAM) {
554 /*
555 * Datagram socket connection is asymmetric.
556 */
557 error = soconnect2(so2, so1);
558 if (error) {
1c79356b
A
559 goto free4;
560 }
561 }
91447636
A
562
563 proc_fdlock(p);
6601e61a
A
564 procfdtbl_releasefd(p, sv[0], NULL);
565 procfdtbl_releasefd(p, sv[1], NULL);
91447636
A
566 fp_drop(p, sv[0], fp1, 1);
567 fp_drop(p, sv[1], fp2, 1);
568 proc_fdunlock(p);
569
570 error = copyout((caddr_t)sv, uap->rsv, 2 * sizeof(int));
1c79356b
A
571#if 0 /* old pipe(2) syscall compatability, unused these days */
572 retval[0] = sv[0]; /* XXX ??? */
573 retval[1] = sv[1]; /* XXX ??? */
574#endif /* 0 */
575 return (error);
576free4:
91447636 577 fp_free(p, sv[1], fp2);
1c79356b 578free3:
91447636 579 fp_free(p, sv[0], fp1);
1c79356b 580free2:
1c79356b
A
581 (void)soclose(so2);
582free1:
583 (void)soclose(so1);
584 return (error);
585}
586
587static int
91447636
A
588sendit(struct proc *p, int s, struct user_msghdr *mp, uio_t uiop,
589 int flags, register_t *retval)
1c79356b 590{
1c79356b
A
591 struct mbuf *control;
592 struct sockaddr *to;
91447636 593 int error;
1c79356b 594 struct socket *so;
91447636 595 user_ssize_t len;
1c79356b 596#if KTRACE
91447636 597 uio_t ktruio = NULL;
1c79356b
A
598#endif
599
600 KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_START, 0,0,0,0,0);
601
91447636
A
602 error = file_socket(s, &so);
603 if (error )
1c79356b
A
604 {
605 KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error,0,0,0,0);
606 return (error);
607 }
91447636 608
1c79356b
A
609 if (mp->msg_name) {
610 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
611 if (error) {
612 KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error,0,0,0,0);
91447636 613 goto out;
1c79356b 614 }
55e303ae 615 AUDIT_ARG(sockaddr, p, to);
91447636 616 } else {
1c79356b 617 to = 0;
91447636 618 }
1c79356b 619 if (mp->msg_control) {
91447636
A
620 if (mp->msg_controllen < ((socklen_t)sizeof(struct cmsghdr))
621#if COMPAT_43_SOCKET
622 && !(mp->msg_flags & MSG_COMPAT)
1c79356b
A
623#endif
624 ) {
625 error = EINVAL;
626 goto bad;
627 }
628 error = sockargs(&control, mp->msg_control,
629 mp->msg_controllen, MT_CONTROL);
630 if (error)
631 goto bad;
91447636
A
632#if COMPAT_43_SOCKET
633 if (mp->msg_flags & MSG_COMPAT) {
1c79356b
A
634 register struct cmsghdr *cm;
635
636 M_PREPEND(control, sizeof(*cm), M_WAIT);
637 if (control == 0) {
638 error = ENOBUFS;
639 goto bad;
640 } else {
641 cm = mtod(control, struct cmsghdr *);
642 cm->cmsg_len = control->m_len;
643 cm->cmsg_level = SOL_SOCKET;
644 cm->cmsg_type = SCM_RIGHTS;
645 }
646 }
647#endif
91447636 648 } else {
1c79356b 649 control = 0;
91447636 650 }
1c79356b 651
9bccf70c 652#if KTRACE
91447636
A
653 if (KTRPOINT(p, KTR_GENIO)) {
654 ktruio = uio_duplicate(uiop);
655 }
9bccf70c 656#endif
91447636
A
657
658 len = uio_resid(uiop);
55e303ae
A
659 if (so == NULL)
660 error = EBADF;
661 else
91447636 662 error = so->so_proto->pr_usrreqs->pru_sosend(so, to, uiop, 0, control,
55e303ae 663 flags);
1c79356b 664 if (error) {
91447636 665 if (uio_resid(uiop) != len && (error == ERESTART ||
1c79356b
A
666 error == EINTR || error == EWOULDBLOCK))
667 error = 0;
9bccf70c
A
668 /* Generation of SIGPIPE can be controlled per socket */
669 if (error == EPIPE && !(so->so_flags & SOF_NOSIGPIPE))
1c79356b
A
670 psignal(p, SIGPIPE);
671 }
672 if (error == 0)
91447636
A
673 *retval = (int)(len - uio_resid(uiop));
674bad:
1c79356b 675#if KTRACE
91447636 676 if (ktruio != NULL) {
9bccf70c 677 if (error == 0) {
91447636
A
678 uio_setresid(ktruio, retval[0]);
679 ktrgenio(p->p_tracep, s, UIO_WRITE, ktruio, error);
9bccf70c 680 }
91447636 681 uio_free(ktruio);
1c79356b
A
682 }
683#endif
1c79356b
A
684 if (to)
685 FREE(to, M_SONAME);
686 KERNEL_DEBUG(DBG_FNC_SENDIT | DBG_FUNC_END, error,0,0,0,0);
91447636
A
687out:
688 file_drop(s);
1c79356b
A
689 return (error);
690}
691
692
1c79356b 693int
91447636 694sendto(struct proc *p, struct sendto_args *uap, register_t *retval)
1c79356b 695{
91447636
A
696 struct user_msghdr msg;
697 int error;
698 uio_t auio = NULL;
1c79356b
A
699
700 KERNEL_DEBUG(DBG_FNC_SENDTO | DBG_FUNC_START, 0,0,0,0,0);
55e303ae 701 AUDIT_ARG(fd, uap->s);
1c79356b 702
91447636
A
703 auio = uio_create(1, 0,
704 (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32),
705 UIO_WRITE);
706 if (auio == NULL) {
707 return (ENOMEM);
708 }
709 uio_addiov(auio, uap->buf, uap->len);
710
1c79356b
A
711 msg.msg_name = uap->to;
712 msg.msg_namelen = uap->tolen;
91447636
A
713 /* no need to set up msg_iov. sendit uses uio_t we send it */
714 msg.msg_iov = 0;
715 msg.msg_iovlen = 0;
1c79356b 716 msg.msg_control = 0;
1c79356b 717 msg.msg_flags = 0;
1c79356b 718
91447636
A
719 error = sendit(p, uap->s, &msg, auio, uap->flags, retval);
720
721 if (auio != NULL) {
722 uio_free(auio);
723 }
724
725#if HACK_FOR_4056224
726 /*
727 * Radar 4056224
728 * Temporary workaround to let send() and recv() work over a pipe for binary compatibility
729 * This will be removed in the release following Tiger
730 */
731 if (error == ENOTSOCK) {
732 struct fileproc *fp;
733
734 if (fp_lookup(p, uap->s, &fp, 0) == 0) {
735 (void) fp_drop(p, uap->s, fp,0);
736
737 if (fp->f_type == DTYPE_PIPE) {
738 struct write_args write_uap;
739 user_ssize_t write_retval;
740
741 if (p->p_pid > last_pid_4056224) {
742 last_pid_4056224 = p->p_pid;
743
744 printf("%s[%d] uses send/recv on a pipe\n",
745 p->p_comm, p->p_pid);
746 }
747
748 bzero(&write_uap, sizeof(struct write_args));
749 write_uap.fd = uap->s;
750 write_uap.cbuf = uap->buf;
751 write_uap.nbyte = uap->len;
752
753 error = write(p, &write_uap, &write_retval);
754 *retval = (int)write_retval;
755 }
756 }
757 }
758#endif /* HACK_FOR_4056224 */
1c79356b 759
91447636
A
760 KERNEL_DEBUG(DBG_FNC_SENDTO | DBG_FUNC_END, error, *retval,0,0,0);
761
762 return(error);
763}
1c79356b 764
91447636
A
765#if COMPAT_43_SOCKET
766int
767osend(__unused struct proc *p,
768 __unused struct osend_args *uap,
769 __unused register_t *retval)
1c79356b 770{
91447636
A
771 /* these are no longer supported and in fact
772 * there is no way to call it directly.
773 * LP64todo - remove this once we're sure there are no clients
774 */
775 return (ENOTSUP);
1c79356b 776}
1c79356b
A
777
778int
91447636
A
779osendmsg(__unused struct proc *p,
780 __unused struct osendmsg_args *uap,
781 __unused register_t *retval)
1c79356b 782{
91447636
A
783 /* these are no longer supported and in fact
784 * there is no way to call it directly.
785 * LP64todo - remove this once we're sure there are no clients
786 */
787 return (ENOTSUP);
1c79356b
A
788}
789#endif
790
1c79356b
A
791
792int
91447636 793sendmsg(struct proc *p, register struct sendmsg_args *uap, register_t *retval)
1c79356b
A
794{
795 struct msghdr msg;
91447636
A
796 struct user_msghdr user_msg;
797 caddr_t msghdrp;
798 int size_of_msghdr;
1c79356b 799 int error;
91447636
A
800 int size_of_iovec;
801 uio_t auio = NULL;
802 struct user_iovec *iovp;
1c79356b
A
803
804 KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_START, 0,0,0,0,0);
55e303ae 805 AUDIT_ARG(fd, uap->s);
91447636
A
806 if (IS_64BIT_PROCESS(p)) {
807 msghdrp = (caddr_t) &user_msg;
808 size_of_msghdr = sizeof(user_msg);
809 size_of_iovec = sizeof(struct user_iovec);
810 }
811 else {
812 msghdrp = (caddr_t) &msg;
813 size_of_msghdr = sizeof(msg);
814 size_of_iovec = sizeof(struct iovec);
815 }
816 error = copyin(uap->msg, msghdrp, size_of_msghdr);
817 if (error)
1c79356b
A
818 {
819 KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, error,0,0,0,0);
820 return (error);
821 }
91447636
A
822
823 /* only need to copy if user process is not 64-bit */
824 if (!IS_64BIT_PROCESS(p)) {
825 user_msg.msg_flags = msg.msg_flags;
826 user_msg.msg_controllen = msg.msg_controllen;
827 user_msg.msg_control = CAST_USER_ADDR_T(msg.msg_control);
828 user_msg.msg_iovlen = msg.msg_iovlen;
829 user_msg.msg_iov = CAST_USER_ADDR_T(msg.msg_iov);
830 user_msg.msg_namelen = msg.msg_namelen;
831 user_msg.msg_name = CAST_USER_ADDR_T(msg.msg_name);
832 }
833
834 if (user_msg.msg_iovlen <= 0 || user_msg.msg_iovlen > UIO_MAXIOV) {
835 KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, EMSGSIZE,0,0,0,0);
836 return (EMSGSIZE);
837 }
838
839 /* allocate a uio large enough to hold the number of iovecs passed */
840 auio = uio_create(user_msg.msg_iovlen, 0,
841 (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32),
842 UIO_WRITE);
843 if (auio == NULL) {
844 error = ENOBUFS;
845 goto done;
846 }
847
848 if (user_msg.msg_iovlen) {
849 /* get location of iovecs within the uio. then copyin the iovecs from
850 * user space.
851 */
852 iovp = uio_iovsaddr(auio);
853 if (iovp == NULL) {
854 error = ENOBUFS;
855 goto done;
856 }
857 error = copyin(user_msg.msg_iov, (caddr_t)iovp, (user_msg.msg_iovlen * size_of_iovec));
858 if (error)
859 goto done;
860 user_msg.msg_iov = CAST_USER_ADDR_T(iovp);
861
862 /* finish setup of uio_t */
863 uio_calculateresid(auio);
864 }
865 else {
866 user_msg.msg_iov = 0;
867 }
868
869#if COMPAT_43_SOCKET
870 user_msg.msg_flags = 0;
1c79356b 871#endif
91447636 872 error = sendit(p, uap->s, &user_msg, auio, uap->flags, retval);
1c79356b 873done:
91447636
A
874 if (auio != NULL) {
875 uio_free(auio);
876 }
1c79356b 877 KERNEL_DEBUG(DBG_FNC_SENDMSG | DBG_FUNC_END, error,0,0,0,0);
91447636 878
1c79356b
A
879 return (error);
880}
881
882static int
91447636 883recvit(p, s, mp, uiop, namelenp, retval)
1c79356b
A
884 register struct proc *p;
885 int s;
91447636
A
886 register struct user_msghdr *mp;
887 uio_t uiop;
888 user_addr_t namelenp;
1c79356b
A
889 register_t *retval;
890{
1c79356b
A
891 int len, error;
892 struct mbuf *m, *control = 0;
91447636 893 user_addr_t ctlbuf;
1c79356b
A
894 struct socket *so;
895 struct sockaddr *fromsa = 0;
91447636 896 struct fileproc *fp;
1c79356b 897#if KTRACE
91447636 898 uio_t ktruio = NULL;
1c79356b
A
899#endif
900
901 KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_START, 0,0,0,0,0);
91447636
A
902 proc_fdlock(p);
903 if ( (error = fp_lookup(p, s, &fp, 1)) ) {
1c79356b 904 KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, error,0,0,0,0);
91447636 905 proc_fdunlock(p);
1c79356b
A
906 return (error);
907 }
91447636
A
908 if (fp->f_type != DTYPE_SOCKET) {
909 fp_drop(p, s, fp,1);
910 proc_fdunlock(p);
911 return(ENOTSOCK);
912 }
1c79356b 913
91447636
A
914 so = (struct socket *)fp->f_data;
915
916 proc_fdunlock(p);
917 if (uio_resid(uiop) < 0) {
918 KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, EINVAL,0,0,0,0);
919 error = EINVAL;
920 goto out1;
1c79356b
A
921 }
922#if KTRACE
923 if (KTRPOINT(p, KTR_GENIO)) {
91447636 924 ktruio = uio_duplicate(uiop);
1c79356b
A
925 }
926#endif
91447636
A
927
928 len = uio_resid(uiop);
55e303ae
A
929 if (so == NULL)
930 error = EBADF;
91447636
A
931 else {
932 error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, uiop,
55e303ae
A
933 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
934 &mp->msg_flags);
91447636 935 }
55e303ae 936 AUDIT_ARG(sockaddr, p, fromsa);
1c79356b 937 if (error) {
91447636 938 if (uio_resid(uiop) != len && (error == ERESTART ||
1c79356b
A
939 error == EINTR || error == EWOULDBLOCK))
940 error = 0;
941 }
942#if KTRACE
91447636 943 if (ktruio != NULL) {
9bccf70c 944 if (error == 0) {
91447636
A
945 uio_setresid(ktruio, len - uio_resid(uiop));
946 ktrgenio(p->p_tracep, s, UIO_WRITE, ktruio, error);
9bccf70c 947 }
91447636 948 uio_free(ktruio);
1c79356b
A
949 }
950#endif
951 if (error)
952 goto out;
91447636 953 *retval = len - uio_resid(uiop);
1c79356b
A
954 if (mp->msg_name) {
955 len = mp->msg_namelen;
956 if (len <= 0 || fromsa == 0)
957 len = 0;
958 else {
959#ifndef MIN
960#define MIN(a,b) ((a)>(b)?(b):(a))
961#endif
962 /* save sa_len before it is destroyed by MSG_COMPAT */
963 len = MIN(len, fromsa->sa_len);
91447636 964#if COMPAT_43_SOCKET
1c79356b
A
965 if (mp->msg_flags & MSG_COMPAT)
966 ((struct osockaddr *)fromsa)->sa_family =
967 fromsa->sa_family;
968#endif
91447636 969 error = copyout(fromsa, mp->msg_name, (unsigned)len);
1c79356b
A
970 if (error)
971 goto out;
972 }
973 mp->msg_namelen = len;
974 if (namelenp &&
975 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
91447636 976#if COMPAT_43_SOCKET
1c79356b
A
977 if (mp->msg_flags & MSG_COMPAT)
978 error = 0; /* old recvfrom didn't check */
979 else
980#endif
981 goto out;
982 }
983 }
984 if (mp->msg_control) {
91447636 985#if COMPAT_43_SOCKET
1c79356b
A
986 /*
987 * We assume that old recvmsg calls won't receive access
988 * rights and other control info, esp. as control info
989 * is always optional and those options didn't exist in 4.3.
990 * If we receive rights, trim the cmsghdr; anything else
991 * is tossed.
992 */
993 if (control && mp->msg_flags & MSG_COMPAT) {
994 if (mtod(control, struct cmsghdr *)->cmsg_level !=
995 SOL_SOCKET ||
996 mtod(control, struct cmsghdr *)->cmsg_type !=
997 SCM_RIGHTS) {
998 mp->msg_controllen = 0;
999 goto out;
1000 }
1001 control->m_len -= sizeof (struct cmsghdr);
1002 control->m_data += sizeof (struct cmsghdr);
1003 }
1004#endif
1005 len = mp->msg_controllen;
1006 m = control;
1007 mp->msg_controllen = 0;
91447636 1008 ctlbuf = mp->msg_control;
1c79356b
A
1009
1010 while (m && len > 0) {
1011 unsigned int tocopy;
1012
1013 if (len >= m->m_len)
1014 tocopy = m->m_len;
1015 else {
1016 mp->msg_flags |= MSG_CTRUNC;
1017 tocopy = len;
1018 }
1019
91447636
A
1020 error = copyout((caddr_t)mtod(m, caddr_t), ctlbuf, tocopy);
1021 if (error)
1c79356b
A
1022 goto out;
1023
1024 ctlbuf += tocopy;
1025 len -= tocopy;
1026 m = m->m_next;
1027 }
1028 mp->msg_controllen = ctlbuf - mp->msg_control;
1029 }
1030out:
1031 if (fromsa)
1032 FREE(fromsa, M_SONAME);
1033 if (control)
1034 m_freem(control);
1035 KERNEL_DEBUG(DBG_FNC_RECVIT | DBG_FUNC_END, error,0,0,0,0);
91447636
A
1036out1:
1037 fp_drop(p, s, fp, 0);
1c79356b
A
1038 return (error);
1039}
1040
1041
1c79356b
A
1042int
1043recvfrom(p, uap, retval)
1044 struct proc *p;
1045 register struct recvfrom_args /* {
1046 int s;
1047 caddr_t buf;
1048 size_t len;
1049 int flags;
1050 caddr_t from;
1051 int *fromlenaddr;
1052 } */ *uap;
1053 register_t *retval;
1054{
91447636 1055 struct user_msghdr msg;
1c79356b 1056 int error;
91447636 1057 uio_t auio = NULL;
1c79356b
A
1058
1059 KERNEL_DEBUG(DBG_FNC_RECVFROM | DBG_FUNC_START, 0,0,0,0,0);
55e303ae 1060 AUDIT_ARG(fd, uap->s);
1c79356b
A
1061
1062 if (uap->fromlenaddr) {
91447636 1063 error = copyin(uap->fromlenaddr,
1c79356b
A
1064 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen));
1065 if (error)
1066 return (error);
1067 } else
1068 msg.msg_namelen = 0;
1069 msg.msg_name = uap->from;
91447636
A
1070 auio = uio_create(1, 0,
1071 (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32),
1072 UIO_READ);
1073 if (auio == NULL) {
1074 return (ENOMEM);
1075 }
1076
1077 uio_addiov(auio, uap->buf, uap->len);
1078 /* no need to set up msg_iov. recvit uses uio_t we send it */
1079 msg.msg_iov = 0;
1080 msg.msg_iovlen = 0;
1c79356b 1081 msg.msg_control = 0;
91447636 1082 msg.msg_controllen = 0;
1c79356b 1083 msg.msg_flags = uap->flags;
91447636
A
1084 error = recvit(p, uap->s, &msg, auio, uap->fromlenaddr, retval);
1085 if (auio != NULL) {
1086 uio_free(auio);
1087 }
1088
1089#if HACK_FOR_4056224
1090 /*
1091 * Radar 4056224
1092 * Temporary workaround to let send() and recv() work over a pipe for binary compatibility
1093 * This will be removed in the release following Tiger
1094 */
1095 if (error == ENOTSOCK && proc_is64bit(p) == 0) {
1096 struct fileproc *fp;
1097
1098 if (fp_lookup(p, uap->s, &fp, 0) == 0) {
1099 (void) fp_drop(p, uap->s, fp,0);
1100
1101 if (fp->f_type == DTYPE_PIPE) {
1102 struct read_args read_uap;
1103 user_ssize_t read_retval;
1104
1105 if (p->p_pid > last_pid_4056224) {
1106 last_pid_4056224 = p->p_pid;
1107
1108 printf("%s[%d] uses send/recv on a pipe\n",
1109 p->p_comm, p->p_pid);
1110 }
1111
1112 bzero(&read_uap, sizeof(struct read_args));
1113 read_uap.fd = uap->s;
1114 read_uap.cbuf = uap->buf;
1115 read_uap.nbyte = uap->len;
1116
1117 error = read(p, &read_uap, &read_retval);
1118 *retval = (int)read_retval;
1119 }
1120 }
1121 }
1122#endif /* HACK_FOR_4056224 */
1123
1c79356b 1124 KERNEL_DEBUG(DBG_FNC_RECVFROM | DBG_FUNC_END, error,0,0,0,0);
91447636
A
1125
1126 return (error);
1c79356b
A
1127}
1128
91447636 1129#if COMPAT_43_SOCKET
1c79356b 1130int
91447636 1131orecvfrom(struct proc *p, struct recvfrom_args *uap, register_t *retval)
1c79356b
A
1132{
1133
1134 uap->flags |= MSG_COMPAT;
55e303ae 1135 return (recvfrom(p, uap, retval));
1c79356b
A
1136}
1137#endif
1138
1139
91447636 1140#if COMPAT_43_SOCKET
1c79356b 1141int
91447636
A
1142orecv(__unused struct proc *p, __unused struct orecv_args *uap,
1143 __unused register_t *retval)
1c79356b 1144{
91447636
A
1145 /* these are no longer supported and in fact
1146 * there is no way to call it directly.
1147 * LP64todo - remove this once we're sure there are no clients
1148 */
1149
1150 return (ENOTSUP);
1c79356b
A
1151}
1152
1153/*
1154 * Old recvmsg. This code takes advantage of the fact that the old msghdr
1155 * overlays the new one, missing only the flags, and with the (old) access
1156 * rights where the control fields are now.
1157 */
1158int
91447636
A
1159orecvmsg(__unused struct proc *p, __unused struct orecvmsg_args *uap,
1160 __unused register_t *retval)
1c79356b 1161{
91447636
A
1162 /* these are no longer supported and in fact
1163 * there is no way to call it directly.
1164 * LP64todo - remove this once we're sure there are no clients
1165 */
1c79356b 1166
91447636 1167 return (ENOTSUP);
1c79356b 1168
1c79356b
A
1169}
1170#endif
1171
1172int
1173recvmsg(p, uap, retval)
1174 struct proc *p;
9bccf70c 1175 struct recvmsg_args *uap;
1c79356b
A
1176 register_t *retval;
1177{
1178 struct msghdr msg;
91447636
A
1179 struct user_msghdr user_msg;
1180 caddr_t msghdrp;
1181 int size_of_msghdr;
1182 user_addr_t uiov;
1c79356b 1183 register int error;
91447636
A
1184 int size_of_iovec;
1185 uio_t auio = NULL;
1186 struct user_iovec *iovp;
1c79356b
A
1187
1188 KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_START, 0,0,0,0,0);
55e303ae 1189 AUDIT_ARG(fd, uap->s);
91447636
A
1190 if (IS_64BIT_PROCESS(p)) {
1191 msghdrp = (caddr_t) &user_msg;
1192 size_of_msghdr = sizeof(user_msg);
1193 size_of_iovec = sizeof(struct user_iovec);
1194 }
1195 else {
1196 msghdrp = (caddr_t) &msg;
1197 size_of_msghdr = sizeof(msg);
1198 size_of_iovec = sizeof(struct iovec);
1199 }
1200 error = copyin(uap->msg, msghdrp, size_of_msghdr);
1201 if (error)
1c79356b
A
1202 {
1203 KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, error,0,0,0,0);
1204 return (error);
1205 }
1206
91447636
A
1207 /* only need to copy if user process is not 64-bit */
1208 if (!IS_64BIT_PROCESS(p)) {
1209 user_msg.msg_flags = msg.msg_flags;
1210 user_msg.msg_controllen = msg.msg_controllen;
1211 user_msg.msg_control = CAST_USER_ADDR_T(msg.msg_control);
1212 user_msg.msg_iovlen = msg.msg_iovlen;
1213 user_msg.msg_iov = CAST_USER_ADDR_T(msg.msg_iov);
1214 user_msg.msg_namelen = msg.msg_namelen;
1215 user_msg.msg_name = CAST_USER_ADDR_T(msg.msg_name);
1216 }
1217
1218 if (user_msg.msg_iovlen <= 0 || user_msg.msg_iovlen > UIO_MAXIOV) {
1219 KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, EMSGSIZE,0,0,0,0);
1220 return (EMSGSIZE);
1221 }
1222
1223#if COMPAT_43_SOCKET
1224 user_msg.msg_flags = uap->flags &~ MSG_COMPAT;
1c79356b 1225#else
91447636 1226 user_msg.msg_flags = uap->flags;
1c79356b 1227#endif
91447636
A
1228
1229 /* allocate a uio large enough to hold the number of iovecs passed */
1230 auio = uio_create(user_msg.msg_iovlen, 0,
1231 (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32),
1232 UIO_READ);
1233 if (auio == NULL) {
1234 error = ENOMEM;
1235 goto done;
1236 }
1237
1238 /* get location of iovecs within the uio. then copyin the iovecs from
1239 * user space.
1240 */
1241 iovp = uio_iovsaddr(auio);
1242 if (iovp == NULL) {
1243 error = ENOMEM;
1244 goto done;
1245 }
1246 uiov = user_msg.msg_iov;
1247 user_msg.msg_iov = CAST_USER_ADDR_T(iovp);
1248 error = copyin(uiov, (caddr_t)iovp, (user_msg.msg_iovlen * size_of_iovec));
1c79356b
A
1249 if (error)
1250 goto done;
91447636
A
1251
1252 /* finish setup of uio_t */
1253 uio_calculateresid(auio);
1254
1255 error = recvit(p, uap->s, &user_msg, auio, 0, retval);
1c79356b 1256 if (!error) {
91447636
A
1257 user_msg.msg_iov = uiov;
1258 /* only need to copy if user process is not 64-bit */
1259 if (!IS_64BIT_PROCESS(p)) {
1260 // LP64todo - do all these change? if not, then no need to copy all of them!
1261 msg.msg_flags = user_msg.msg_flags;
1262 msg.msg_controllen = user_msg.msg_controllen;
1263 msg.msg_control = CAST_DOWN(caddr_t, user_msg.msg_control);
1264 msg.msg_iovlen = user_msg.msg_iovlen;
1265 msg.msg_iov = (struct iovec *) CAST_DOWN(caddr_t, user_msg.msg_iov);
1266 msg.msg_namelen = user_msg.msg_namelen;
1267 msg.msg_name = CAST_DOWN(caddr_t, user_msg.msg_name);
1268 }
1269 error = copyout(msghdrp, uap->msg, size_of_msghdr);
1c79356b
A
1270 }
1271done:
91447636
A
1272 if (auio != NULL) {
1273 uio_free(auio);
1274 }
1c79356b
A
1275 KERNEL_DEBUG(DBG_FNC_RECVMSG | DBG_FUNC_END, error,0,0,0,0);
1276 return (error);
1277}
1278
1279/* ARGSUSED */
1280int
91447636 1281shutdown(__unused struct proc *p, struct shutdown_args *uap, __unused register_t *retval)
1c79356b 1282{
91447636 1283 struct socket * so;
1c79356b
A
1284 int error;
1285
55e303ae 1286 AUDIT_ARG(fd, uap->s);
91447636 1287 error = file_socket(uap->s, &so);
1c79356b
A
1288 if (error)
1289 return (error);
91447636
A
1290 if (so == NULL) {
1291 error = EBADF;
1292 goto out;
1293 }
1294 error = soshutdown((struct socket *)so, uap->how);
1295out:
1296 file_drop(uap->s);
1297 return(error);
1c79356b
A
1298}
1299
1300
1301
1302
1303
1304/* ARGSUSED */
1305int
91447636 1306setsockopt(struct proc *p, struct setsockopt_args *uap, __unused register_t *retval)
1c79356b 1307{
91447636 1308 struct socket * so;
1c79356b
A
1309 struct sockopt sopt;
1310 int error;
1311
55e303ae 1312 AUDIT_ARG(fd, uap->s);
1c79356b
A
1313 if (uap->val == 0 && uap->valsize != 0)
1314 return (EFAULT);
1315 if (uap->valsize < 0)
1316 return (EINVAL);
1317
91447636 1318 error = file_socket(uap->s, &so);
1c79356b
A
1319 if (error)
1320 return (error);
1321
1322 sopt.sopt_dir = SOPT_SET;
1323 sopt.sopt_level = uap->level;
1324 sopt.sopt_name = uap->name;
1325 sopt.sopt_val = uap->val;
1326 sopt.sopt_valsize = uap->valsize;
1327 sopt.sopt_p = p;
1328
91447636
A
1329 if (so == NULL) {
1330 error = EINVAL;
1331 goto out;
1332 }
1333 error = sosetopt(so, &sopt);
1334out:
1335 file_drop(uap->s);
1336 return(error);
1c79356b
A
1337}
1338
1339
1340
1341int
91447636 1342getsockopt(struct proc *p, struct getsockopt_args *uap, __unused register_t *retval)
1c79356b 1343{
91447636
A
1344 int error;
1345 socklen_t valsize;
1346 struct sockopt sopt;
1347 struct socket * so;
1c79356b 1348
91447636 1349 error = file_socket(uap->s, &so);
1c79356b
A
1350 if (error)
1351 return (error);
1352 if (uap->val) {
91447636 1353 error = copyin(uap->avalsize, (caddr_t)&valsize, sizeof (valsize));
1c79356b 1354 if (error)
91447636
A
1355 goto out;
1356 if (valsize < 0) {
1357 error = EINVAL;
1358 goto out;
1359 }
1c79356b
A
1360 } else
1361 valsize = 0;
1362
1363 sopt.sopt_dir = SOPT_GET;
1364 sopt.sopt_level = uap->level;
1365 sopt.sopt_name = uap->name;
1366 sopt.sopt_val = uap->val;
1367 sopt.sopt_valsize = (size_t)valsize; /* checked non-negative above */
1368 sopt.sopt_p = p;
1369
91447636
A
1370 if (so == NULL) {
1371 error = EBADF;
1372 goto out;
1373 }
1374 error = sogetopt((struct socket *)so, &sopt);
1c79356b
A
1375 if (error == 0) {
1376 valsize = sopt.sopt_valsize;
91447636 1377 error = copyout((caddr_t)&valsize, uap->avalsize, sizeof (valsize));
1c79356b 1378 }
91447636
A
1379out:
1380 file_drop(uap->s);
1c79356b
A
1381 return (error);
1382}
1383
1384
1385/*
1386 * Get socket name.
1387 */
1388/* ARGSUSED */
1389static int
91447636
A
1390getsockname1(__unused struct proc *p, struct getsockname_args *uap, __unused register_t *retval,
1391 int compat)
1c79356b 1392{
91447636 1393 struct socket *so;
1c79356b 1394 struct sockaddr *sa;
91447636 1395 socklen_t len;
1c79356b
A
1396 int error;
1397
91447636 1398 error = file_socket(uap->fdes, &so);
1c79356b
A
1399 if (error)
1400 return (error);
91447636 1401 error = copyin(uap->alen, (caddr_t)&len, sizeof(socklen_t));
1c79356b 1402 if (error)
91447636
A
1403 goto out;
1404 if (so == NULL) {
1405 error = EBADF;
1406 goto out;
1407 }
1c79356b 1408 sa = 0;
91447636 1409 socket_lock(so, 1);
1c79356b 1410 error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
91447636
A
1411 if (error == 0)
1412 {
1413 struct socket_filter_entry *filter;
1414 int filtered = 0;
1415 for (filter = so->so_filt; filter && error == 0;
1416 filter = filter->sfe_next_onsocket) {
1417 if (filter->sfe_filter->sf_filter.sf_getsockname) {
1418 if (!filtered) {
1419 filtered = 1;
1420 sflt_use(so);
1421 socket_unlock(so, 0);
1422 }
1423 error = filter->sfe_filter->sf_filter.sf_getsockname(filter->sfe_cookie,
1424 so, &sa);
1425 }
1426 }
1427
1428 if (error == EJUSTRETURN)
1429 error = 0;
1430
1431 if (filtered) {
1432 socket_lock(so, 0);
1433 sflt_unuse(so);
1434 }
1435 }
1436 socket_unlock(so, 1);
1c79356b
A
1437 if (error)
1438 goto bad;
1439 if (sa == 0) {
1440 len = 0;
1441 goto gotnothing;
1442 }
1443
1444 len = MIN(len, sa->sa_len);
91447636 1445#if COMPAT_43_SOCKET
1c79356b
A
1446 if (compat)
1447 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1448#endif
91447636 1449 error = copyout((caddr_t)sa, uap->asa, len);
1c79356b
A
1450 if (error == 0)
1451gotnothing:
91447636 1452 error = copyout((caddr_t)&len, uap->alen, sizeof(socklen_t));
1c79356b
A
1453bad:
1454 if (sa)
1455 FREE(sa, M_SONAME);
91447636
A
1456out:
1457 file_drop(uap->fdes);
1c79356b
A
1458 return (error);
1459}
1460
1461int
91447636 1462getsockname(struct proc *p, struct getsockname_args *uap, register_t *retval)
1c79356b 1463{
1c79356b
A
1464 return (getsockname1(p, uap, retval, 0));
1465}
1466
91447636 1467#if COMPAT_43_SOCKET
1c79356b 1468int
91447636 1469ogetsockname(struct proc *p, struct getsockname_args *uap, register_t *retval)
1c79356b 1470{
1c79356b
A
1471 return (getsockname1(p, uap, retval, 1));
1472}
91447636 1473#endif /* COMPAT_43_SOCKET */
1c79356b
A
1474
1475/*
1476 * Get name of peer for connected socket.
1477 */
1478/* ARGSUSED */
1479int
91447636
A
1480getpeername1(__unused struct proc *p, struct getpeername_args *uap, __unused register_t *retval,
1481 int compat)
1c79356b 1482{
91447636 1483 struct socket *so;
1c79356b 1484 struct sockaddr *sa;
91447636 1485 socklen_t len;
1c79356b
A
1486 int error;
1487
91447636 1488 error = file_socket(uap->fdes, &so);
1c79356b
A
1489 if (error)
1490 return (error);
91447636
A
1491 if (so == NULL) {
1492 error = EBADF;
1493 goto out;
1494 }
1495
1496 socket_lock(so, 1);
1497
1498 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1499 socket_unlock(so, 1);
1500 error = ENOTCONN;
1501 goto out;
1502 }
1503 error = copyin(uap->alen, (caddr_t)&len, sizeof(socklen_t));
1504 if (error) {
1505 socket_unlock(so, 1);
1506 goto out;
1507 }
1c79356b
A
1508 sa = 0;
1509 error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
91447636
A
1510 if (error == 0)
1511 {
1512 struct socket_filter_entry *filter;
1513 int filtered = 0;
1514 for (filter = so->so_filt; filter && error == 0;
1515 filter = filter->sfe_next_onsocket) {
1516 if (filter->sfe_filter->sf_filter.sf_getpeername) {
1517 if (!filtered) {
1518 filtered = 1;
1519 sflt_use(so);
1520 socket_unlock(so, 0);
1521 }
1522 error = filter->sfe_filter->sf_filter.sf_getpeername(filter->sfe_cookie,
1523 so, &sa);
1524 }
1525 }
1526
1527 if (error == EJUSTRETURN)
1528 error = 0;
1529
1530 if (filtered) {
1531 socket_lock(so, 0);
1532 sflt_unuse(so);
1533 }
1534 }
1535 socket_unlock(so, 1);
1c79356b
A
1536 if (error)
1537 goto bad;
1538 if (sa == 0) {
1539 len = 0;
1540 goto gotnothing;
1541 }
1542 len = MIN(len, sa->sa_len);
91447636 1543#if COMPAT_43_SOCKET
1c79356b
A
1544 if (compat)
1545 ((struct osockaddr *)sa)->sa_family =
1546 sa->sa_family;
1547#endif
91447636 1548 error = copyout(sa, uap->asa, len);
1c79356b
A
1549 if (error)
1550 goto bad;
1551gotnothing:
91447636 1552 error = copyout((caddr_t)&len, uap->alen, sizeof(socklen_t));
1c79356b
A
1553bad:
1554 if (sa) FREE(sa, M_SONAME);
91447636
A
1555out:
1556 file_drop(uap->fdes);
1c79356b
A
1557 return (error);
1558}
1559
1560int
91447636 1561getpeername(struct proc *p, struct getpeername_args *uap, register_t *retval)
1c79356b
A
1562{
1563
1564 return (getpeername1(p, uap, retval, 0));
1565}
1566
91447636 1567#if COMPAT_43_SOCKET
1c79356b 1568int
91447636 1569ogetpeername(struct proc *p, struct getpeername_args *uap, register_t *retval)
1c79356b
A
1570{
1571
91447636 1572 return (getpeername1(p, uap, retval, 1));
1c79356b 1573}
91447636 1574#endif /* COMPAT_43_SOCKET */
1c79356b
A
1575
1576int
91447636 1577sockargs(mp, data, buflen, type)
1c79356b 1578 struct mbuf **mp;
91447636 1579 user_addr_t data;
1c79356b
A
1580 int buflen, type;
1581{
1582 register struct sockaddr *sa;
1583 register struct mbuf *m;
1584 int error;
1585
1586 if ((u_int)buflen > MLEN) {
91447636 1587#if COMPAT_43_SOCKET
1c79356b
A
1588 if (type == MT_SONAME && (u_int)buflen <= 112)
1589 buflen = MLEN; /* unix domain compat. hack */
1590 else
1591#endif
91447636
A
1592 if ((u_int)buflen > MCLBYTES)
1593 return (EINVAL);
1c79356b
A
1594 }
1595 m = m_get(M_WAIT, type);
1596 if (m == NULL)
1597 return (ENOBUFS);
91447636
A
1598 if ((u_int)buflen > MLEN) {
1599 MCLGET(m, M_WAIT);
1600 if ((m->m_flags & M_EXT) == 0) {
1601 m_free(m);
1602 return ENOBUFS;
1603 }
1604 }
1c79356b 1605 m->m_len = buflen;
91447636 1606 error = copyin(data, mtod(m, caddr_t), (u_int)buflen);
1c79356b
A
1607 if (error)
1608 (void) m_free(m);
1609 else {
1610 *mp = m;
1611 if (type == MT_SONAME) {
1612 sa = mtod(m, struct sockaddr *);
1613
91447636 1614#if COMPAT_43_SOCKET && BYTE_ORDER != BIG_ENDIAN
1c79356b
A
1615 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1616 sa->sa_family = sa->sa_len;
1617#endif
1618 sa->sa_len = buflen;
1619 }
1620 }
1621 return (error);
1622}
1623
91447636
A
1624/*
1625 * Given a user_addr_t of length len, allocate and fill out a *sa.
1626 */
1c79356b 1627int
91447636 1628getsockaddr(struct sockaddr **namp, user_addr_t uaddr, size_t len)
1c79356b
A
1629{
1630 struct sockaddr *sa;
1631 int error;
1632
1633 if (len > SOCK_MAXADDRLEN)
1634 return ENAMETOOLONG;
1635
1636 if (len == 0)
1637 return EINVAL;
1638
1639 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
91447636
A
1640 if (sa == NULL) {
1641 return ENOMEM;
1642 }
1643 error = copyin(uaddr, (caddr_t)sa, len);
1c79356b
A
1644 if (error) {
1645 FREE(sa, M_SONAME);
1646 } else {
91447636 1647#if COMPAT_43_SOCKET && BYTE_ORDER != BIG_ENDIAN
1c79356b
A
1648 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1649 sa->sa_family = sa->sa_len;
1650#endif
1651 sa->sa_len = len;
1652 *namp = sa;
1653 }
1654 return error;
1655}
1656
1c79356b
A
1657
1658#if SENDFILE
1659/*
1660 * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-))
1661 * XXX - The sf_buf functions are currently private to sendfile(2), so have
1662 * been made static, but may be useful in the future for doing zero-copy in
1663 * other parts of the networking code.
1664 */
1665static void
1666sf_buf_init(void *arg)
1667{
1668 int i;
1669
1670 SLIST_INIT(&sf_freelist);
91447636
A
1671 kmem_alloc_pageable(kernel_map, &sf_base, nsfbufs * PAGE_SIZE);
1672 MALLOC(sf_bufs, struct sf_buf *, nsfbufs * sizeof(struct sf_buf), M_TEMP, M_NOWAIT|M_ZERO);
1673 if (sf_bufs == NULL)
1674 return; /* XXX silently fail leaving sf_bufs NULL */
1675
1c79356b
A
1676 for (i = 0; i < nsfbufs; i++) {
1677 sf_bufs[i].kva = sf_base + i * PAGE_SIZE;
1678 SLIST_INSERT_HEAD(&sf_freelist, &sf_bufs[i], free_list);
1679 }
1680}
1681
1682/*
1683 * Get an sf_buf from the freelist. Will block if none are available.
1684 */
1685static struct sf_buf *
1686sf_buf_alloc()
1687{
1688 struct sf_buf *sf;
1c79356b 1689
1c79356b
A
1690 while ((sf = SLIST_FIRST(&sf_freelist)) == NULL) {
1691 sf_buf_alloc_want = 1;
1692 tsleep(&sf_freelist, PVM, "sfbufa", 0);
1693 }
1694 SLIST_REMOVE_HEAD(&sf_freelist, free_list);
1c79356b
A
1695 sf->refcnt = 1;
1696 return (sf);
1697}
1698
1699#define dtosf(x) (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT])
1700static void
1701sf_buf_ref(caddr_t addr, u_int size)
1702{
1703 struct sf_buf *sf;
1704
1705 sf = dtosf(addr);
1706 if (sf->refcnt == 0)
1707 panic("sf_buf_ref: referencing a free sf_buf");
1708 sf->refcnt++;
1709}
1710
1711/*
1712 * Lose a reference to an sf_buf. When none left, detach mapped page
1713 * and release resources back to the system.
1714 *
1715 * Must be called at splimp.
1716 */
1717static void
1718sf_buf_free(caddr_t addr, u_int size)
1719{
1720 struct sf_buf *sf;
1721 struct vm_page *m;
1c79356b
A
1722
1723 sf = dtosf(addr);
1724 if (sf->refcnt == 0)
1725 panic("sf_buf_free: freeing free sf_buf");
1726 sf->refcnt--;
1727 if (sf->refcnt == 0) {
1728 pmap_qremove((vm_offset_t)addr, 1);
1729 m = sf->m;
1c79356b
A
1730 vm_page_unwire(m, 0);
1731 /*
1732 * Check for the object going away on us. This can
1733 * happen since we don't hold a reference to it.
1734 * If so, we're responsible for freeing the page.
1735 */
1736 if (m->wire_count == 0 && m->object == NULL)
1737 vm_page_lock_queues();
1738 vm_page_free(m);
1739 vm_page_unlock_queues();
1c79356b
A
1740 sf->m = NULL;
1741 SLIST_INSERT_HEAD(&sf_freelist, sf, free_list);
1742 if (sf_buf_alloc_want) {
1743 sf_buf_alloc_want = 0;
1744 wakeup(&sf_freelist);
1745 }
1746 }
1747}
1748
1749/*
1750 * sendfile(2).
1751 * int sendfile(int fd, int s, off_t offset, size_t nbytes,
1752 * struct sf_hdtr *hdtr, off_t *sbytes, int flags)
1753 *
1754 * Send a file specified by 'fd' and starting at 'offset' to a socket
1755 * specified by 's'. Send only 'nbytes' of the file or until EOF if
1756 * nbytes == 0. Optionally add a header and/or trailer to the socket
1757 * output. If specified, write the total number of bytes sent into *sbytes.
1758 */
1759int
1760sendfile(struct proc *p, struct sendfile_args *uap)
1761{
91447636 1762 struct fileproc *fp;
1c79356b
A
1763 struct vnode *vp;
1764 struct vm_object *obj;
1765 struct socket *so;
1766 struct mbuf *m;
1767 struct sf_buf *sf;
1768 struct vm_page *pg;
1769 struct writev_args nuap;
1770 struct sf_hdtr hdtr;
1771 off_t off, xfsize, sbytes = 0;
1772 int error = 0, s;
0c530ab8 1773 kauth_cred_t safecred;
1c79356b 1774
91447636
A
1775 if (sf_bufs == NULL) {
1776 /* Fail if initialization failed */
1777 return ENOSYS;
1778 }
1779
1c79356b
A
1780 /*
1781 * Do argument checking. Must be a regular file in, stream
1782 * type and connected socket out, positive offset.
1783 */
91447636 1784 if (error = fp_getfvp(p, uap->fd, &fp, &vp))
1c79356b 1785 goto done;
91447636
A
1786 if (fp->f_flag & FREAD) == 0) {
1787 error = EBADF;
1788 goto done1;
1c79356b 1789 }
1c79356b
A
1790 obj = vp->v_object;
1791 if (vp->v_type != VREG || obj == NULL) {
1792 error = EINVAL;
91447636 1793 goto done1;
1c79356b 1794 }
91447636 1795 error = file_socket(uap->s, &so);
1c79356b 1796 if (error)
91447636 1797 goto done1;
55e303ae
A
1798 if (so == NULL) {
1799 error = EBADF;
91447636 1800 goto done2;
55e303ae 1801 }
91447636
A
1802
1803 socket_lock(so, 1);
1804
1c79356b
A
1805 if (so->so_type != SOCK_STREAM) {
1806 error = EINVAL;
91447636 1807 goto done3;
1c79356b
A
1808 }
1809 if ((so->so_state & SS_ISCONNECTED) == 0) {
1810 error = ENOTCONN;
91447636 1811 goto done3;
1c79356b
A
1812 }
1813 if (uap->offset < 0) {
1814 error = EINVAL;
91447636 1815 goto done3;
1c79356b
A
1816 }
1817
1818 /*
1819 * If specified, get the pointer to the sf_hdtr struct for
1820 * any headers/trailers.
1821 */
1822 if (uap->hdtr != NULL) {
91447636 1823 error = copyin(CAST_USER_ADDR_T(uap->hdtr), &hdtr, sizeof(hdtr));
1c79356b 1824 if (error)
91447636 1825 goto done3;
1c79356b
A
1826 /*
1827 * Send any headers. Wimp out and use writev(2).
1828 */
1829 if (hdtr.headers != NULL) {
1830 nuap.fd = uap->s;
1831 nuap.iovp = hdtr.headers;
1832 nuap.iovcnt = hdtr.hdr_cnt;
1833 error = writev(p, &nuap);
1834 if (error)
91447636 1835 goto done3;
1c79356b
A
1836 sbytes += p->p_retval[0];
1837 }
1838 }
1839
1840 /*
1841 * Protect against multiple writers to the socket.
1842 */
1843 (void) sblock(&so->so_snd, M_WAIT);
1844
1845 /*
1846 * Loop through the pages in the file, starting with the requested
1847 * offset. Get a file page (do I/O if necessary), map the file page
1848 * into an sf_buf, attach an mbuf header to the sf_buf, and queue
1849 * it on the socket.
1850 */
1851 for (off = uap->offset; ; off += xfsize, sbytes += xfsize) {
1852 vm_object_offset_t pindex;
1853 vm_object_offset_t pgoff;
1854
1855 pindex = OFF_TO_IDX(off);
1856retry_lookup:
1857 /*
1858 * Calculate the amount to transfer. Not to exceed a page,
1859 * the EOF, or the passed in nbytes.
1860 */
1861 xfsize = obj->un_pager.vnp.vnp_size - off;
1862 if (xfsize > PAGE_SIZE_64)
1863 xfsize = PAGE_SIZE;
1864 pgoff = (vm_object_offset_t)(off & PAGE_MASK_64);
1865 if (PAGE_SIZE - pgoff < xfsize)
1866 xfsize = PAGE_SIZE_64 - pgoff;
1867 if (uap->nbytes && xfsize > (uap->nbytes - sbytes))
1868 xfsize = uap->nbytes - sbytes;
1869 if (xfsize <= 0)
1870 break;
1871 /*
1872 * Optimize the non-blocking case by looking at the socket space
1873 * before going to the extra work of constituting the sf_buf.
1874 */
1875 if ((so->so_state & SS_NBIO) && sbspace(&so->so_snd) <= 0) {
1876 if (so->so_state & SS_CANTSENDMORE)
1877 error = EPIPE;
1878 else
1879 error = EAGAIN;
91447636
A
1880 sbunlock(&so->so_snd, 0); /* will release lock */
1881 goto done2;
1c79356b
A
1882 }
1883 /*
1884 * Attempt to look up the page. If the page doesn't exist or the
1885 * part we're interested in isn't valid, then read it from disk.
1886 * If some other part of the kernel has this page (i.e. it's busy),
1887 * then disk I/O may be occuring on it, so wait and retry.
1888 */
1889 pg = vm_page_lookup(obj, pindex);
1890 if (pg == NULL || (!(pg->flags & PG_BUSY) && !pg->busy &&
1891 !vm_page_is_valid(pg, pgoff, xfsize))) {
1892 struct uio auio;
1893 struct iovec aiov;
1894 int bsize;
1895
1896 if (pg == NULL) {
1897 pg = vm_page_alloc(obj, pindex, VM_ALLOC_NORMAL);
1898 if (pg == NULL) {
1899 VM_WAIT;
1900 goto retry_lookup;
1901 }
1902 /*
1903 * don't just clear PG_BUSY manually -
1904 * vm_page_alloc() should be considered opaque,
1905 * use the VM routine provided to clear
1906 * PG_BUSY.
1907 */
1908 vm_page_wakeup(pg);
1909
1910 }
1911 /*
1912 * Ensure that our page is still around when the I/O completes.
1913 */
1914 vm_page_io_start(pg);
1915 vm_page_wire(pg);
1916 /*
1917 * Get the page from backing store.
1918 */
91447636 1919 bsize = vp->v_mount->mnt_vfsstat.f_iosize;
1c79356b
A
1920 auio.uio_iov = &aiov;
1921 auio.uio_iovcnt = 1;
1922 aiov.iov_base = 0;
1923 aiov.iov_len = MAXBSIZE;
1c79356b
A
1924 auio.uio_offset = trunc_page(off);
1925 auio.uio_segflg = UIO_NOCOPY;
1926 auio.uio_rw = UIO_READ;
91447636 1927 uio_setresid(&auio, MAXBSIZE);
0c530ab8 1928 safecred = kauth_cred_proc_ref(p);
1c79356b 1929 error = VOP_READ(vp, &auio, IO_VMIO | ((MAXBSIZE / bsize) << 16),
0c530ab8
A
1930 safecred);
1931 kauth_cred_unref(&safecred);
1c79356b
A
1932 vm_page_flag_clear(pg, PG_ZERO);
1933 vm_page_io_finish(pg);
1934 if (error) {
1935 vm_page_unwire(pg, 0);
1936 /*
1937 * See if anyone else might know about this page.
1938 * If not and it is not valid, then free it.
1939 */
1940 if (pg->wire_count == 0 && pg->valid == 0 &&
1941 pg->busy == 0 && !(pg->flags & PG_BUSY) &&
1942 pg->hold_count == 0)
1943 vm_page_lock_queues();
1944 vm_page_free(pg);
1945 vm_page_unlock_queues();
91447636
A
1946 sbunlock(&so->so_snd, 0); /* will release socket lock */
1947 goto done2;
1c79356b
A
1948 }
1949 } else {
1950 if ((pg->flags & PG_BUSY) || pg->busy) {
1951 s = splvm();
1952 if ((pg->flags & PG_BUSY) || pg->busy) {
1953 /*
1954 * Page is busy. Wait and retry.
1955 */
1956 vm_page_flag_set(pg, PG_WANTED);
1957 tsleep(pg, PVM, "sfpbsy", 0);
1c79356b
A
1958 goto retry_lookup;
1959 }
1c79356b
A
1960 }
1961 /*
1962 * Protect from having the page ripped out from beneath us.
1963 */
1964 vm_page_wire(pg);
1965 }
1966 /*
1967 * Allocate a kernel virtual page and insert the physical page
1968 * into it.
1969 */
1970 sf = sf_buf_alloc();
1971 sf->m = pg;
1972 pmap_qenter(sf->kva, &pg, 1);
1973 /*
1974 * Get an mbuf header and set it up as having external storage.
1975 */
1976 MGETHDR(m, M_WAIT, MT_DATA);
91447636
A
1977 if (m == NULL) {
1978 error = ENOBUFS;
1979 sbunlock(&so->so_snd, 0); /* will release socket lock */
1980 goto done2;
1981 }
1c79356b
A
1982 m->m_ext.ext_free = sf_buf_free;
1983 m->m_ext.ext_ref = sf_buf_ref;
1984 m->m_ext.ext_buf = (void *)sf->kva;
1985 m->m_ext.ext_size = PAGE_SIZE;
1986 m->m_data = (char *) sf->kva + pgoff;
1987 m->m_flags |= M_EXT;
1988 m->m_pkthdr.len = m->m_len = xfsize;
1989 /*
1990 * Add the buffer to the socket buffer chain.
1991 */
1c79356b
A
1992retry_space:
1993 /*
1994 * Make sure that the socket is still able to take more data.
1995 * CANTSENDMORE being true usually means that the connection
1996 * was closed. so_error is true when an error was sensed after
1997 * a previous send.
1998 * The state is checked after the page mapping and buffer
1999 * allocation above since those operations may block and make
2000 * any socket checks stale. From this point forward, nothing
2001 * blocks before the pru_send (or more accurately, any blocking
2002 * results in a loop back to here to re-check).
2003 */
2004 if ((so->so_state & SS_CANTSENDMORE) || so->so_error) {
2005 if (so->so_state & SS_CANTSENDMORE) {
2006 error = EPIPE;
2007 } else {
2008 error = so->so_error;
2009 so->so_error = 0;
2010 }
2011 m_freem(m);
91447636
A
2012 sbunlock(&so->so_snd, 0); /* will release socket lock */
2013 goto done2;
1c79356b
A
2014 }
2015 /*
2016 * Wait for socket space to become available. We do this just
2017 * after checking the connection state above in order to avoid
2018 * a race condition with sbwait().
2019 */
2020 if (sbspace(&so->so_snd) < so->so_snd.sb_lowat) {
2021 if (so->so_state & SS_NBIO) {
2022 m_freem(m);
91447636 2023 sbunlock(&so->so_snd, 0); /* will release socket lock */
1c79356b 2024 error = EAGAIN;
91447636 2025 goto done2;
1c79356b
A
2026 }
2027 error = sbwait(&so->so_snd);
2028 /*
2029 * An error from sbwait usually indicates that we've
2030 * been interrupted by a signal. If we've sent anything
2031 * then return bytes sent, otherwise return the error.
2032 */
2033 if (error) {
2034 m_freem(m);
91447636
A
2035 sbunlock(&so->so_snd, 0);
2036 goto done2;
1c79356b
A
2037 }
2038 goto retry_space;
2039 }
2040 error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, p);
2041 splx(s);
2042 if (error) {
91447636
A
2043 sbunlock(&so->so_snd, 0); /* will release socket lock */
2044 goto done2;
1c79356b
A
2045 }
2046 }
91447636 2047 sbunlock(&so->so_snd, 0); /* will release socket lock */
1c79356b
A
2048
2049 /*
2050 * Send trailers. Wimp out and use writev(2).
2051 */
2052 if (uap->hdtr != NULL && hdtr.trailers != NULL) {
2053 nuap.fd = uap->s;
2054 nuap.iovp = hdtr.trailers;
2055 nuap.iovcnt = hdtr.trl_cnt;
2056 error = writev(p, &nuap);
2057 if (error)
91447636 2058 goto done2;
1c79356b
A
2059 sbytes += p->p_retval[0];
2060 }
91447636
A
2061done2:
2062 file_drop(uap->s);
2063done1:
2064 file_drop(uap->fd);
1c79356b
A
2065done:
2066 if (uap->sbytes != NULL) {
91447636
A
2067 /* XXX this appears bogus for some early failure conditions */
2068 copyout(&sbytes, CAST_USER_ADDR_T(uap->sbytes), sizeof(off_t));
1c79356b
A
2069 }
2070 return (error);
91447636
A
2071done3:
2072 socket_unlock(so, 1);
2073 goto done2;
1c79356b
A
2074}
2075
2076#endif