1 /* $NetBSD: uipc_syscalls.c,v 1.138 2009/12/20 09:36:06 dsl Exp $ */
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1982, 1986, 1989, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.138 2009/12/20 09:36:06 dsl Exp $");
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/filedesc.h>
74 #include <sys/malloc.h>
76 #include <sys/protosw.h>
77 #include <sys/socket.h>
78 #include <sys/socketvar.h>
79 #include <sys/signalvar.h>
81 #include <sys/ktrace.h>
82 #include <sys/event.h>
83 #include <sys/kauth.h>
85 #include <sys/mount.h>
86 #include <sys/syscallargs.h>
88 #include <uvm/uvm_extern.h>
91 * System call interface to the socket abstraction.
93 extern const struct fileops socketops
;
96 sys___socket30(struct lwp
*l
, const struct sys___socket30_args
*uap
, register_t
*retval
)
99 syscallarg(int) domain;
100 syscallarg(int) type;
101 syscallarg(int) protocol;
105 error
= fsocreate(SCARG(uap
, domain
), NULL
, SCARG(uap
, type
),
106 SCARG(uap
, protocol
), l
, &fd
);
114 sys_bind(struct lwp
*l
, const struct sys_bind_args
*uap
, register_t
*retval
)
118 syscallarg(const struct sockaddr *) name;
119 syscallarg(unsigned int) namelen;
124 error
= sockargs(&nam
, SCARG(uap
, name
), SCARG(uap
, namelen
),
129 return do_sys_bind(l
, SCARG(uap
, s
), nam
);
133 do_sys_bind(struct lwp
*l
, int fd
, struct mbuf
*nam
)
138 if ((error
= fd_getsock(fd
, &so
)) != 0) {
142 MCLAIM(nam
, so
->so_mowner
);
143 error
= sobind(so
, nam
, l
);
151 sys_listen(struct lwp
*l
, const struct sys_listen_args
*uap
, register_t
*retval
)
155 syscallarg(int) backlog;
160 if ((error
= fd_getsock(SCARG(uap
, s
), &so
)) != 0)
162 error
= solisten(so
, SCARG(uap
, backlog
), l
);
163 fd_putfile(SCARG(uap
, s
));
168 do_sys_accept(struct lwp
*l
, int sock
, struct mbuf
**name
, register_t
*new_sock
)
173 struct socket
*so
, *so2
;
174 short wakeup_state
= 0;
176 if ((fp
= fd_getfile(sock
)) == NULL
)
178 if (fp
->f_type
!= DTYPE_SOCKET
) {
182 if ((error
= fd_allocfile(&fp2
, &fd
)) != 0) {
186 nam
= m_get(M_WAIT
, MT_SONAME
);
190 if (!(so
->so_proto
->pr_flags
& PR_LISTEN
)) {
194 if ((so
->so_options
& SO_ACCEPTCONN
) == 0) {
198 if (so
->so_nbio
&& so
->so_qlen
== 0) {
202 while (so
->so_qlen
== 0 && so
->so_error
== 0) {
203 if (so
->so_state
& SS_CANTRCVMORE
) {
204 so
->so_error
= ECONNABORTED
;
207 if (wakeup_state
& SS_RESTARTSYS
) {
211 error
= sowait(so
, true, 0);
215 wakeup_state
= so
->so_state
;
218 error
= so
->so_error
;
222 /* connection has been removed from the listen queue */
223 KNOTE(&so
->so_rcv
.sb_sel
.sel_klist
, NOTE_SUBMIT
);
224 so2
= TAILQ_FIRST(&so
->so_q
);
225 if (soqremque(so2
, 1) == 0)
227 fp2
->f_type
= DTYPE_SOCKET
;
228 fp2
->f_flag
= fp
->f_flag
;
229 fp2
->f_ops
= &socketops
;
231 error
= soaccept(so2
, nam
);
232 so2
->so_cred
= kauth_cred_dup(so
->so_cred
);
235 /* an error occurred, free the file descriptor and mbuf */
236 kauth_cred_free(so2
->so_cred
);
238 mutex_enter(&fp2
->f_lock
);
240 mutex_exit(&fp2
->f_lock
);
242 fd_abort(curproc
, NULL
, fd
);
244 fd_affix(curproc
, fp2
, fd
);
253 fd_abort(curproc
, fp2
, fd
);
258 sys_accept(struct lwp
*l
, const struct sys_accept_args
*uap
, register_t
*retval
)
262 syscallarg(struct sockaddr *) name;
263 syscallarg(unsigned int *) anamelen;
268 error
= do_sys_accept(l
, SCARG(uap
, s
), &name
, retval
);
271 error
= copyout_sockname(SCARG(uap
, name
), SCARG(uap
, anamelen
),
272 MSG_LENUSRSPACE
, name
);
277 if (fd_getfile(fd
) != NULL
)
285 sys_connect(struct lwp
*l
, const struct sys_connect_args
*uap
, register_t
*retval
)
289 syscallarg(const struct sockaddr *) name;
290 syscallarg(unsigned int) namelen;
295 error
= sockargs(&nam
, SCARG(uap
, name
), SCARG(uap
, namelen
),
299 return do_sys_connect(l
, SCARG(uap
, s
), nam
);
303 do_sys_connect(struct lwp
*l
, int fd
, struct mbuf
*nam
)
309 if ((error
= fd_getsock(fd
, &so
)) != 0) {
314 MCLAIM(nam
, so
->so_mowner
);
315 if ((so
->so_state
& SS_ISCONNECTING
) != 0) {
320 error
= soconnect(so
, nam
, l
);
323 if (so
->so_nbio
&& (so
->so_state
& SS_ISCONNECTING
) != 0) {
327 while ((so
->so_state
& SS_ISCONNECTING
) != 0 && so
->so_error
== 0) {
328 error
= sowait(so
, true, 0);
329 if (__predict_false((so
->so_state
& SS_ISABORTING
) != 0)) {
335 if (error
== EINTR
|| error
== ERESTART
)
341 error
= so
->so_error
;
346 so
->so_state
&= ~SS_ISCONNECTING
;
347 if (error
== ERESTART
)
357 sys_socketpair(struct lwp
*l
, const struct sys_socketpair_args
*uap
, register_t
*retval
)
360 syscallarg(int) domain;
361 syscallarg(int) type;
362 syscallarg(int) protocol;
363 syscallarg(int *) rsv;
366 struct socket
*so1
, *so2
;
367 int fd
, error
, sv
[2];
371 error
= socreate(SCARG(uap
, domain
), &so1
, SCARG(uap
, type
),
372 SCARG(uap
, protocol
), l
, NULL
);
375 error
= socreate(SCARG(uap
, domain
), &so2
, SCARG(uap
, type
),
376 SCARG(uap
, protocol
), l
, so1
);
379 if ((error
= fd_allocfile(&fp1
, &fd
)) != 0)
382 fp1
->f_flag
= FREAD
|FWRITE
;
383 fp1
->f_type
= DTYPE_SOCKET
;
384 fp1
->f_ops
= &socketops
;
386 if ((error
= fd_allocfile(&fp2
, &fd
)) != 0)
388 fp2
->f_flag
= FREAD
|FWRITE
;
389 fp2
->f_type
= DTYPE_SOCKET
;
390 fp2
->f_ops
= &socketops
;
394 error
= soconnect2(so1
, so2
);
395 if (error
== 0 && SCARG(uap
, type
) == SOCK_DGRAM
) {
397 * Datagram socket connection is asymmetric.
399 error
= soconnect2(so2
, so1
);
403 error
= copyout(sv
, SCARG(uap
, rsv
), 2 * sizeof(int));
405 fd_affix(p
, fp2
, sv
[1]);
406 fd_affix(p
, fp1
, sv
[0]);
409 fd_abort(p
, fp2
, sv
[1]);
411 fd_abort(p
, fp1
, sv
[0]);
420 sys_sendto(struct lwp
*l
, const struct sys_sendto_args
*uap
, register_t
*retval
)
424 syscallarg(const void *) buf;
425 syscallarg(size_t) len;
426 syscallarg(int) flags;
427 syscallarg(const struct sockaddr *) to;
428 syscallarg(unsigned int) tolen;
433 msg
.msg_name
= __UNCONST(SCARG(uap
, to
)); /* XXXUNCONST kills const */
434 msg
.msg_namelen
= SCARG(uap
, tolen
);
437 msg
.msg_control
= NULL
;
439 aiov
.iov_base
= __UNCONST(SCARG(uap
, buf
)); /* XXXUNCONST kills const */
440 aiov
.iov_len
= SCARG(uap
, len
);
441 return do_sys_sendmsg(l
, SCARG(uap
, s
), &msg
, SCARG(uap
, flags
), retval
);
445 sys_sendmsg(struct lwp
*l
, const struct sys_sendmsg_args
*uap
, register_t
*retval
)
449 syscallarg(const struct msghdr *) msg;
450 syscallarg(int) flags;
455 error
= copyin(SCARG(uap
, msg
), &msg
, sizeof(msg
));
459 msg
.msg_flags
= MSG_IOVUSRSPACE
;
460 return do_sys_sendmsg(l
, SCARG(uap
, s
), &msg
, SCARG(uap
, flags
), retval
);
464 do_sys_sendmsg(struct lwp
*l
, int s
, struct msghdr
*mp
, int flags
,
468 int i
, len
, error
, iovlen
;
469 struct mbuf
*to
, *control
;
472 struct iovec aiov
[UIO_SMALLIOV
], *iov
= aiov
;
473 struct iovec
*ktriov
= NULL
;
475 ktrkuser("msghdr", mp
, sizeof *mp
);
477 /* If the caller passed us stuff in mbufs, we must free them */
478 if (mp
->msg_flags
& MSG_NAMEMBUF
)
483 if (mp
->msg_flags
& MSG_CONTROLMBUF
)
484 control
= mp
->msg_control
;
488 if (mp
->msg_flags
& MSG_IOVUSRSPACE
) {
489 if ((unsigned int)mp
->msg_iovlen
> UIO_SMALLIOV
) {
490 if ((unsigned int)mp
->msg_iovlen
> IOV_MAX
) {
494 iov
= malloc(sizeof(struct iovec
) * mp
->msg_iovlen
,
497 if (mp
->msg_iovlen
!= 0) {
498 error
= copyin(mp
->msg_iov
, iov
,
499 (size_t)(mp
->msg_iovlen
* sizeof(struct iovec
)));
506 auio
.uio_iov
= mp
->msg_iov
;
507 auio
.uio_iovcnt
= mp
->msg_iovlen
;
508 auio
.uio_rw
= UIO_WRITE
;
509 auio
.uio_offset
= 0; /* XXX */
511 KASSERT(l
== curlwp
);
512 auio
.uio_vmspace
= l
->l_proc
->p_vmspace
;
514 for (i
= 0, tiov
= mp
->msg_iov
; i
< mp
->msg_iovlen
; i
++, tiov
++) {
516 /* cannot happen; iov_len is unsigned */
517 if (tiov
->iov_len
< 0) {
523 * Writes return ssize_t because -1 is returned on error.
524 * Therefore, we must restrict the length to SSIZE_MAX to
525 * avoid garbage return values.
527 auio
.uio_resid
+= tiov
->iov_len
;
528 if (tiov
->iov_len
> SSIZE_MAX
|| auio
.uio_resid
> SSIZE_MAX
) {
534 if (mp
->msg_name
&& to
== NULL
) {
535 error
= sockargs(&to
, mp
->msg_name
, mp
->msg_namelen
,
541 if (mp
->msg_control
) {
542 if (mp
->msg_controllen
< CMSG_ALIGN(sizeof(struct cmsghdr
))) {
546 if (control
== NULL
) {
547 error
= sockargs(&control
, mp
->msg_control
,
548 mp
->msg_controllen
, MT_CONTROL
);
554 if (ktrpoint(KTR_GENIO
)) {
555 iovlen
= auio
.uio_iovcnt
* sizeof(struct iovec
);
556 ktriov
= malloc(iovlen
, M_TEMP
, M_WAITOK
);
557 memcpy(ktriov
, auio
.uio_iov
, iovlen
);
560 if ((error
= fd_getsock(s
, &so
)) != 0)
564 MCLAIM(to
, so
->so_mowner
);
566 MCLAIM(control
, so
->so_mowner
);
568 len
= auio
.uio_resid
;
569 error
= (*so
->so_send
)(so
, to
, &auio
, NULL
, control
, flags
, l
);
570 /* Protocol is responsible for freeing 'control' */
576 if (auio
.uio_resid
!= len
&& (error
== ERESTART
||
577 error
== EINTR
|| error
== EWOULDBLOCK
))
579 if (error
== EPIPE
&& (flags
& MSG_NOSIGNAL
) == 0) {
580 mutex_enter(proc_lock
);
581 psignal(l
->l_proc
, SIGPIPE
);
582 mutex_exit(proc_lock
);
586 *retsize
= len
- auio
.uio_resid
;
589 if (ktriov
!= NULL
) {
590 ktrgeniov(s
, UIO_WRITE
, ktriov
, *retsize
, error
);
591 free(ktriov
, M_TEMP
);
605 sys_recvfrom(struct lwp
*l
, const struct sys_recvfrom_args
*uap
, register_t
*retval
)
609 syscallarg(void *) buf;
610 syscallarg(size_t) len;
611 syscallarg(int) flags;
612 syscallarg(struct sockaddr *) from;
613 syscallarg(unsigned int *) fromlenaddr;
623 aiov
.iov_base
= SCARG(uap
, buf
);
624 aiov
.iov_len
= SCARG(uap
, len
);
625 msg
.msg_control
= NULL
;
626 msg
.msg_flags
= SCARG(uap
, flags
) & MSG_USERFLAGS
;
628 error
= do_sys_recvmsg(l
, SCARG(uap
, s
), &msg
, &from
, NULL
, retval
);
632 error
= copyout_sockname(SCARG(uap
, from
), SCARG(uap
, fromlenaddr
),
633 MSG_LENUSRSPACE
, from
);
640 sys_recvmsg(struct lwp
*l
, const struct sys_recvmsg_args
*uap
, register_t
*retval
)
644 syscallarg(struct msghdr *) msg;
645 syscallarg(int) flags;
649 struct mbuf
*from
, *control
;
651 error
= copyin(SCARG(uap
, msg
), &msg
, sizeof(msg
));
655 msg
.msg_flags
= (SCARG(uap
, flags
) & MSG_USERFLAGS
) | MSG_IOVUSRSPACE
;
657 error
= do_sys_recvmsg(l
, SCARG(uap
, s
), &msg
, &from
,
658 msg
.msg_control
!= NULL
? &control
: NULL
, retval
);
662 if (msg
.msg_control
!= NULL
)
663 error
= copyout_msg_control(l
, &msg
, control
);
666 error
= copyout_sockname(msg
.msg_name
, &msg
.msg_namelen
, 0,
671 ktrkuser("msghdr", &msg
, sizeof msg
);
672 error
= copyout(&msg
, SCARG(uap
, msg
), sizeof(msg
));
679 * Adjust for a truncated SCM_RIGHTS control message.
680 * This means closing any file descriptors that aren't present
681 * in the returned buffer.
682 * m is the mbuf holding the (already externalized) SCM_RIGHTS message.
685 free_rights(struct mbuf
*m
)
691 nfd
= m
->m_len
< CMSG_SPACE(sizeof(int)) ? 0
692 : (m
->m_len
- CMSG_SPACE(sizeof(int))) / sizeof(int) + 1;
693 fdv
= (int *) CMSG_DATA(mtod(m
,struct cmsghdr
*));
694 for (i
= 0; i
< nfd
; i
++) {
695 if (fd_getfile(fdv
[i
]) != NULL
)
696 (void)fd_close(fdv
[i
]);
701 free_control_mbuf(struct lwp
*l
, struct mbuf
*control
, struct mbuf
*uncopied
)
704 struct cmsghdr
*cmsg
;
705 bool do_free_rights
= false;
707 while (control
!= NULL
) {
708 cmsg
= mtod(control
, struct cmsghdr
*);
709 if (control
== uncopied
)
710 do_free_rights
= true;
711 if (do_free_rights
&& cmsg
->cmsg_level
== SOL_SOCKET
712 && cmsg
->cmsg_type
== SCM_RIGHTS
)
713 free_rights(control
);
714 next
= control
->m_next
;
720 /* Copy socket control/CMSG data to user buffer, frees the mbuf */
722 copyout_msg_control(struct lwp
*l
, struct msghdr
*mp
, struct mbuf
*control
)
724 int i
, len
, error
= 0;
725 struct cmsghdr
*cmsg
;
729 len
= mp
->msg_controllen
;
730 if (len
<= 0 || control
== 0) {
731 mp
->msg_controllen
= 0;
732 free_control_mbuf(l
, control
, control
);
736 q
= (char *)mp
->msg_control
;
738 for (m
= control
; m
!= NULL
; ) {
739 cmsg
= mtod(m
, struct cmsghdr
*);
742 mp
->msg_flags
|= MSG_CTRUNC
;
743 if (cmsg
->cmsg_level
== SOL_SOCKET
744 && cmsg
->cmsg_type
== SCM_RIGHTS
)
745 /* Do not truncate me ... */
749 error
= copyout(mtod(m
, void *), q
, i
);
750 ktrkuser("msgcontrol", mtod(m
, void *), i
);
752 /* We must free all the SCM_RIGHTS */
765 free_control_mbuf(l
, control
, m
);
767 mp
->msg_controllen
= q
- (char *)mp
->msg_control
;
772 do_sys_recvmsg(struct lwp
*l
, int s
, struct msghdr
*mp
, struct mbuf
**from
,
773 struct mbuf
**control
, register_t
*retsize
)
776 struct iovec aiov
[UIO_SMALLIOV
], *iov
= aiov
;
778 int i
, len
, error
, iovlen
;
780 struct iovec
*ktriov
;
782 ktrkuser("msghdr", mp
, sizeof *mp
);
788 if ((error
= fd_getsock(s
, &so
)) != 0)
791 if (mp
->msg_flags
& MSG_IOVUSRSPACE
) {
792 if ((unsigned int)mp
->msg_iovlen
> UIO_SMALLIOV
) {
793 if ((unsigned int)mp
->msg_iovlen
> IOV_MAX
) {
797 iov
= malloc(sizeof(struct iovec
) * mp
->msg_iovlen
,
800 if (mp
->msg_iovlen
!= 0) {
801 error
= copyin(mp
->msg_iov
, iov
,
802 (size_t)(mp
->msg_iovlen
* sizeof(struct iovec
)));
808 auio
.uio_iov
= mp
->msg_iov
;
809 auio
.uio_iovcnt
= mp
->msg_iovlen
;
810 auio
.uio_rw
= UIO_READ
;
811 auio
.uio_offset
= 0; /* XXX */
813 KASSERT(l
== curlwp
);
814 auio
.uio_vmspace
= l
->l_proc
->p_vmspace
;
817 for (i
= 0; i
< mp
->msg_iovlen
; i
++, tiov
++) {
819 /* cannot happen iov_len is unsigned */
820 if (tiov
->iov_len
< 0) {
826 * Reads return ssize_t because -1 is returned on error.
827 * Therefore we must restrict the length to SSIZE_MAX to
828 * avoid garbage return values.
830 auio
.uio_resid
+= tiov
->iov_len
;
831 if (tiov
->iov_len
> SSIZE_MAX
|| auio
.uio_resid
> SSIZE_MAX
) {
838 if (ktrpoint(KTR_GENIO
)) {
839 iovlen
= auio
.uio_iovcnt
* sizeof(struct iovec
);
840 ktriov
= malloc(iovlen
, M_TEMP
, M_WAITOK
);
841 memcpy(ktriov
, auio
.uio_iov
, iovlen
);
844 len
= auio
.uio_resid
;
845 mp
->msg_flags
&= MSG_USERFLAGS
;
846 error
= (*so
->so_receive
)(so
, from
, &auio
, NULL
, control
,
848 len
-= auio
.uio_resid
;
850 if (error
!= 0 && len
!= 0
851 && (error
== ERESTART
|| error
== EINTR
|| error
== EWOULDBLOCK
))
852 /* Some data transferred */
855 if (ktriov
!= NULL
) {
856 ktrgeniov(s
, UIO_READ
, ktriov
, len
, error
);
857 free(ktriov
, M_TEMP
);
863 if (control
!= NULL
) {
864 free_control_mbuf(l
, *control
, *control
);
878 sys_shutdown(struct lwp
*l
, const struct sys_shutdown_args
*uap
, register_t
*retval
)
887 if ((error
= fd_getsock(SCARG(uap
, s
), &so
)) != 0)
890 error
= soshutdown(so
, SCARG(uap
, how
));
892 fd_putfile(SCARG(uap
, s
));
898 sys_setsockopt(struct lwp
*l
, const struct sys_setsockopt_args
*uap
, register_t
*retval
)
902 syscallarg(int) level;
903 syscallarg(int) name;
904 syscallarg(const void *) val;
905 syscallarg(unsigned int) valsize;
912 len
= SCARG(uap
, valsize
);
913 if (len
> 0 && SCARG(uap
, val
) == NULL
)
919 if ((error
= fd_getsock(SCARG(uap
, s
), &so
)) != 0)
922 sockopt_init(&sopt
, SCARG(uap
, level
), SCARG(uap
, name
), len
);
925 error
= copyin(SCARG(uap
, val
), sopt
.sopt_data
, len
);
930 error
= sosetopt(so
, &sopt
);
933 sockopt_destroy(&sopt
);
934 fd_putfile(SCARG(uap
, s
));
940 sys_getsockopt(struct lwp
*l
, const struct sys_getsockopt_args
*uap
, register_t
*retval
)
944 syscallarg(int) level;
945 syscallarg(int) name;
946 syscallarg(void *) val;
947 syscallarg(unsigned int *) avalsize;
951 unsigned int valsize
, len
;
954 if (SCARG(uap
, val
) != NULL
) {
955 error
= copyin(SCARG(uap
, avalsize
), &valsize
, sizeof(valsize
));
961 if ((error
= fd_getsock(SCARG(uap
, s
), &so
)) != 0)
964 sockopt_init(&sopt
, SCARG(uap
, level
), SCARG(uap
, name
), 0);
966 error
= sogetopt(so
, &sopt
);
971 len
= min(valsize
, sopt
.sopt_size
);
972 error
= copyout(sopt
.sopt_data
, SCARG(uap
, val
), len
);
976 error
= copyout(&len
, SCARG(uap
, avalsize
), sizeof(len
));
982 sockopt_destroy(&sopt
);
983 fd_putfile(SCARG(uap
, s
));
987 #ifdef PIPE_SOCKETPAIR
990 sys_pipe(struct lwp
*l
, const void *v
, register_t
*retval
)
993 struct socket
*rso
, *wso
;
998 if ((error
= socreate(AF_LOCAL
, &rso
, SOCK_STREAM
, 0, l
, NULL
)) != 0)
1000 if ((error
= socreate(AF_LOCAL
, &wso
, SOCK_STREAM
, 0, l
, rso
)) != 0)
1002 /* remember this socket pair implements a pipe */
1003 wso
->so_state
|= SS_ISAPIPE
;
1004 rso
->so_state
|= SS_ISAPIPE
;
1005 if ((error
= fd_allocfile(&rf
, &fd
)) != 0)
1009 rf
->f_type
= DTYPE_SOCKET
;
1010 rf
->f_ops
= &socketops
;
1012 if ((error
= fd_allocfile(&wf
, &fd
)) != 0)
1014 wf
->f_flag
= FWRITE
;
1015 wf
->f_type
= DTYPE_SOCKET
;
1016 wf
->f_ops
= &socketops
;
1020 error
= unp_connect2(wso
, rso
, PRU_CONNECT2
);
1024 fd_affix(p
, wf
, (int)retval
[1]);
1025 fd_affix(p
, rf
, (int)retval
[0]);
1028 fd_abort(p
, wf
, (int)retval
[1]);
1030 fd_abort(p
, rf
, (int)retval
[0]);
1037 #endif /* PIPE_SOCKETPAIR */
1044 do_sys_getsockname(struct lwp
*l
, int fd
, int which
, struct mbuf
**nam
)
1050 if ((error
= fd_getsock(fd
, &so
)) != 0)
1053 m
= m_getclr(M_WAIT
, MT_SONAME
);
1054 MCLAIM(m
, so
->so_mowner
);
1057 if (which
== PRU_PEERADDR
1058 && (so
->so_state
& (SS_ISCONNECTED
| SS_ISCONFIRMING
)) == 0) {
1062 error
= (*so
->so_proto
->pr_usrreq
)(so
, which
, NULL
, m
, NULL
,
1073 copyout_sockname(struct sockaddr
*asa
, unsigned int *alen
, int flags
,
1080 /* Assume application not interested */
1083 if (flags
& MSG_LENUSRSPACE
) {
1084 error
= copyin(alen
, &len
, sizeof(len
));
1096 if (len
> addr
->m_len
)
1098 /* Maybe this ought to copy a chain ? */
1099 ktrkuser("sockname", mtod(addr
, void *), len
);
1100 error
= copyout(mtod(addr
, void *), asa
, len
);
1104 if (flags
& MSG_LENUSRSPACE
)
1105 error
= copyout(&len
, alen
, sizeof(len
));
1118 sys_getsockname(struct lwp
*l
, const struct sys_getsockname_args
*uap
, register_t
*retval
)
1121 syscallarg(int) fdes;
1122 syscallarg(struct sockaddr *) asa;
1123 syscallarg(unsigned int *) alen;
1128 error
= do_sys_getsockname(l
, SCARG(uap
, fdes
), PRU_SOCKADDR
, &m
);
1132 error
= copyout_sockname(SCARG(uap
, asa
), SCARG(uap
, alen
),
1133 MSG_LENUSRSPACE
, m
);
1140 * Get name of peer for connected socket.
1144 sys_getpeername(struct lwp
*l
, const struct sys_getpeername_args
*uap
, register_t
*retval
)
1147 syscallarg(int) fdes;
1148 syscallarg(struct sockaddr *) asa;
1149 syscallarg(unsigned int *) alen;
1154 error
= do_sys_getsockname(l
, SCARG(uap
, fdes
), PRU_PEERADDR
, &m
);
1158 error
= copyout_sockname(SCARG(uap
, asa
), SCARG(uap
, alen
),
1159 MSG_LENUSRSPACE
, m
);
1166 * XXX In a perfect world, we wouldn't pass around socket control
1167 * XXX arguments in mbufs, and this could go away.
1170 sockargs(struct mbuf
**mp
, const void *bf
, size_t buflen
, int type
)
1172 struct sockaddr
*sa
;
1177 * We can't allow socket names > UCHAR_MAX in length, since that
1178 * will overflow sa_len. Control data more than a page size in
1179 * length is just too much.
1181 if (buflen
> (type
== MT_SONAME
? UCHAR_MAX
: PAGE_SIZE
))
1184 /* Allocate an mbuf to hold the arguments. */
1185 m
= m_get(M_WAIT
, type
);
1186 /* can't claim. don't who to assign it to. */
1187 if (buflen
> MLEN
) {
1189 * Won't fit into a regular mbuf, so we allocate just
1190 * enough external storage to hold the argument.
1192 MEXTMALLOC(m
, buflen
, M_WAITOK
);
1195 error
= copyin(bf
, mtod(m
, void *), buflen
);
1200 ktrkuser("sockargs", mtod(m
, void *), buflen
);
1202 if (type
== MT_SONAME
) {
1203 sa
= mtod(m
, struct sockaddr
*);
1204 #if BYTE_ORDER != BIG_ENDIAN
1206 * 4.3BSD compat thing - need to stay, since bind(2),
1207 * connect(2), sendto(2) were not versioned for COMPAT_43.
1209 if (sa
->sa_family
== 0 && sa
->sa_len
< AF_MAX
)
1210 sa
->sa_family
= sa
->sa_len
;
1212 sa
->sa_len
= buflen
;