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