2 * Copyright (c) 1995 Søren Schmidt
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD: src/sys/compat/linux/linux_socket.c,v 1.19.2.8 2001/11/07 20:33:55 marcel Exp $
29 * $DragonFly: src/sys/emulation/linux/linux_socket.c,v 1.28 2008/07/10 00:19:27 aggelos Exp $
32 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/sysproto.h>
36 #include <sys/fcntl.h>
38 #include <sys/kern_syscall.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
42 #include <sys/malloc.h>
45 #include <sys/mplock2.h>
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/ip.h>
51 #include <arch_linux/linux.h>
52 #include <arch_linux/linux_proto.h>
53 #include "linux_socket.h"
54 #include "linux_util.h"
57 * Copyin a sockaddr structure provided by a Linux binary. Linux uses
58 * the 4.3BSD sockaddr structure which has no sa_len field. We must
59 * pass 4.4BSD sockaddr structures when we call native functions in the
60 * BSD kernel. This function does the conversion for us.
62 * Also, our socket calls require the sockaddr structure length to agree
63 * with the address family. Linux does not, so we must force it.
65 * This function should only need to be called from linux_connect()
69 linux_getsockaddr(struct sockaddr
**namp
, struct sockaddr
*uaddr
, size_t len
)
72 uint16_t family
; /* XXX: must match Linux sockaddr */
78 if (len
> SOCK_MAXADDRLEN
)
80 error
= copyin(uaddr
, &family
, sizeof(family
));
85 * Force the sa_len field to match the address family.
89 sa_len
= sizeof(struct sockaddr_in
);
92 sa_len
= sizeof(struct sockaddr_in6
);
96 * This is the default behavior of the old
97 * linux_to_bsd_namelen() function. NOTE! The
98 * minimum length we allocate must cover sa->sa_len and
101 sa_len
= offsetof(struct sockaddr
, sa_data
[0]);
107 MALLOC(sa
, struct sockaddr
*, sa_len
, M_SONAME
, M_WAITOK
);
108 error
= copyin(uaddr
, sa
, sa_len
);
113 * Convert to the 4.4BSD sockaddr structure.
115 sa
->sa_family
= *(sa_family_t
*)sa
;
124 * Transform a 4.4BSD sockaddr structure into a Linux sockaddr structure
125 * and copy it out to a user address.
128 linux_copyout_sockaddr(struct sockaddr
*sa
, struct sockaddr
*uaddr
, int sa_len
)
132 if (sa_len
< (int)sizeof(u_short
))
135 *(u_short
*)sa
= sa
->sa_family
;
136 error
= copyout(sa
, uaddr
, sa_len
);
142 linux_to_bsd_domain(int domain
)
146 case LINUX_AF_UNSPEC
:
156 case LINUX_AF_APPLETALK
:
157 return (AF_APPLETALK
);
163 linux_to_bsd_sockopt_level(int level
)
167 case LINUX_SOL_SOCKET
:
174 linux_to_bsd_ip_sockopt(int opt
)
182 case LINUX_IP_OPTIONS
:
184 case LINUX_IP_MULTICAST_IF
:
185 return (IP_MULTICAST_IF
);
186 case LINUX_IP_MULTICAST_TTL
:
187 return (IP_MULTICAST_TTL
);
188 case LINUX_IP_MULTICAST_LOOP
:
189 return (IP_MULTICAST_LOOP
);
190 case LINUX_IP_ADD_MEMBERSHIP
:
191 return (IP_ADD_MEMBERSHIP
);
192 case LINUX_IP_DROP_MEMBERSHIP
:
193 return (IP_DROP_MEMBERSHIP
);
194 case LINUX_IP_HDRINCL
:
201 linux_to_bsd_so_sockopt(int opt
)
207 case LINUX_SO_REUSEADDR
:
208 return (SO_REUSEADDR
);
213 case LINUX_SO_DONTROUTE
:
214 return (SO_DONTROUTE
);
215 case LINUX_SO_BROADCAST
:
216 return (SO_BROADCAST
);
217 case LINUX_SO_SNDBUF
:
219 case LINUX_SO_RCVBUF
:
221 case LINUX_SO_KEEPALIVE
:
222 return (SO_KEEPALIVE
);
223 case LINUX_SO_OOBINLINE
:
224 return (SO_OOBINLINE
);
225 case LINUX_SO_LINGER
:
232 linux_to_bsd_msg_flags(int flags
)
236 if (flags
& LINUX_MSG_OOB
)
237 ret_flags
|= MSG_OOB
;
238 if (flags
& LINUX_MSG_PEEK
)
239 ret_flags
|= MSG_PEEK
;
240 if (flags
& LINUX_MSG_DONTROUTE
)
241 ret_flags
|= MSG_DONTROUTE
;
242 if (flags
& LINUX_MSG_CTRUNC
)
243 ret_flags
|= MSG_CTRUNC
;
244 if (flags
& LINUX_MSG_TRUNC
)
245 ret_flags
|= MSG_TRUNC
;
246 if (flags
& LINUX_MSG_DONTWAIT
)
247 ret_flags
|= MSG_DONTWAIT
;
248 if (flags
& LINUX_MSG_EOR
)
249 ret_flags
|= MSG_EOR
;
250 if (flags
& LINUX_MSG_WAITALL
)
251 ret_flags
|= MSG_WAITALL
;
252 #if 0 /* not handled */
253 if (flags
& LINUX_MSG_PROXY
)
255 if (flags
& LINUX_MSG_FIN
)
257 if (flags
& LINUX_MSG_SYN
)
259 if (flags
& LINUX_MSG_CONFIRM
)
261 if (flags
& LINUX_MSG_RST
)
263 if (flags
& LINUX_MSG_ERRQUEUE
)
265 if (flags
& LINUX_MSG_NOSIGNAL
)
271 struct linux_socket_args
{
278 linux_socket(struct linux_socket_args
*args
, int *res
)
280 struct linux_socket_args linux_args
;
282 int error
, domain
, optval
;
284 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
288 domain
= linux_to_bsd_domain(linux_args
.domain
);
292 error
= kern_socket(domain
, linux_args
.type
, linux_args
.protocol
, res
);
294 /* Copy back the return value from socket() */
295 if (error
== 0 && linux_args
.type
== SOCK_RAW
&&
296 (linux_args
.protocol
== IPPROTO_RAW
|| linux_args
.protocol
== 0) &&
297 linux_args
.domain
== AF_INET
) {
298 /* It's a raw IP socket: set the IP_HDRINCL option. */
300 sopt
.sopt_dir
= SOPT_SET
;
301 sopt
.sopt_level
= IPPROTO_IP
;
302 sopt
.sopt_name
= IP_HDRINCL
;
303 sopt
.sopt_val
= &optval
;
304 sopt
.sopt_valsize
= sizeof(optval
);
307 /* We ignore any error returned by setsockopt() */
308 kern_setsockopt(*res
, &sopt
);
314 struct linux_bind_args
{
316 struct sockaddr
*name
;
321 linux_bind(struct linux_bind_args
*args
, int *res
)
323 struct linux_bind_args linux_args
;
327 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
330 error
= linux_getsockaddr(&sa
, linux_args
.name
, linux_args
.namelen
);
334 error
= kern_bind(linux_args
.s
, sa
);
340 struct linux_connect_args
{
342 struct sockaddr
* name
;
347 linux_connect(struct linux_connect_args
*args
, int *res
)
349 struct thread
*td
= curthread
; /* XXX */
350 struct proc
*p
= td
->td_proc
;
351 struct linux_connect_args linux_args
;
359 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
362 error
= linux_getsockaddr(&sa
, linux_args
.name
, linux_args
.namelen
);
366 error
= kern_connect(linux_args
.s
, 0, sa
);
369 if (error
!= EISCONN
)
373 * Linux doesn't return EISCONN the first time it occurs,
374 * when on a non-blocking socket. Instead it returns the
375 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
377 error
= holdsock(p
->p_fd
, linux_args
.s
, &fp
);
381 if (fp
->f_flag
& FNONBLOCK
) {
382 so
= (struct socket
*)fp
->f_data
;
383 if (so
->so_emuldata
== 0)
384 error
= so
->so_error
;
385 so
->so_emuldata
= (void *)1;
391 struct linux_listen_args
{
397 linux_listen(struct linux_listen_args
*args
, int *res
)
399 struct linux_listen_args linux_args
;
402 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
406 error
= kern_listen(linux_args
.s
, linux_args
.backlog
);
411 struct linux_accept_args
{
413 struct sockaddr
*addr
;
418 linux_accept(struct linux_accept_args
*args
, int *res
)
420 struct thread
*td
= curthread
;
421 struct linux_accept_args linux_args
;
422 struct sockaddr
*sa
= NULL
;
423 union fcntl_dat dat
= { 0 };
426 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
430 if (linux_args
.addr
) {
431 error
= copyin(linux_args
.namelen
, &sa_len
, sizeof(sa_len
));
435 error
= kern_accept(linux_args
.s
, 0, &sa
, &sa_len
, res
);
439 * Return a namelen of zero for older code which
440 * might ignore the return value from accept().
443 copyout(&sa_len
, linux_args
.namelen
,
444 sizeof(*linux_args
.namelen
));
446 error
= linux_copyout_sockaddr(sa
, linux_args
.addr
,
449 error
= copyout(&sa_len
, linux_args
.namelen
,
450 sizeof(*linux_args
.namelen
));
456 error
= kern_accept(linux_args
.s
, 0, NULL
, 0, res
);
463 * linux appears not to copy flags from the parent socket to the
464 * accepted one, so we must clear the flags in the new descriptor.
465 * Ignore any errors, because we already have an open fd.
467 kern_fcntl(*res
, F_SETFL
, &dat
, td
->td_ucred
);
471 struct linux_getsockname_args
{
473 struct sockaddr
*addr
;
478 linux_getsockname(struct linux_getsockname_args
*args
, int *res
)
480 struct linux_getsockname_args linux_args
;
481 struct sockaddr
*sa
= NULL
;
485 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
488 error
= copyin(linux_args
.namelen
, &sa_len
, sizeof(sa_len
));
492 error
= kern_getsockname(linux_args
.s
, &sa
, &sa_len
);
495 error
= linux_copyout_sockaddr(sa
, linux_args
.addr
, sa_len
);
497 error
= copyout(&sa_len
, linux_args
.namelen
,
498 sizeof(*linux_args
.namelen
));
504 struct linux_getpeername_args
{
506 struct sockaddr
*addr
;
511 linux_getpeername(struct linux_getpeername_args
*args
, int *res
)
513 struct linux_getpeername_args linux_args
;
514 struct sockaddr
*sa
= NULL
;
517 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
520 error
= copyin(linux_args
.namelen
, &sa_len
, sizeof(sa_len
));
524 error
= kern_getpeername(linux_args
.s
, &sa
, &sa_len
);
527 error
= linux_copyout_sockaddr(sa
, linux_args
.addr
, sa_len
);
529 error
= copyout(&sa_len
, linux_args
.namelen
,
530 sizeof(*linux_args
.namelen
));
536 struct linux_socketpair_args
{
544 linux_socketpair(struct linux_socketpair_args
*args
, int *res
)
546 struct linux_socketpair_args linux_args
;
547 int error
, domain
, sockv
[2];
549 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
553 domain
= linux_to_bsd_domain(linux_args
.domain
);
556 error
= kern_socketpair(domain
, linux_args
.type
, linux_args
.protocol
,
560 error
= copyout(sockv
, linux_args
.rsv
, sizeof(sockv
));
564 struct linux_send_args
{
572 linux_send(struct linux_send_args
*args
, size_t *res
)
574 struct linux_send_args linux_args
;
575 struct thread
*td
= curthread
;
580 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
584 aiov
.iov_base
= linux_args
.msg
;
585 aiov
.iov_len
= linux_args
.len
;
586 auio
.uio_iov
= &aiov
;
589 auio
.uio_resid
= linux_args
.len
;
590 auio
.uio_segflg
= UIO_USERSPACE
;
591 auio
.uio_rw
= UIO_WRITE
;
594 error
= kern_sendmsg(linux_args
.s
, NULL
, &auio
, NULL
,
595 linux_args
.flags
, res
);
600 struct linux_recv_args
{
608 linux_recv(struct linux_recv_args
*args
, size_t *res
)
610 struct linux_recv_args linux_args
;
611 struct thread
*td
= curthread
;
616 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
620 aiov
.iov_base
= linux_args
.msg
;
621 aiov
.iov_len
= linux_args
.len
;
622 auio
.uio_iov
= &aiov
;
625 auio
.uio_resid
= linux_args
.len
;
626 auio
.uio_segflg
= UIO_USERSPACE
;
627 auio
.uio_rw
= UIO_READ
;
630 error
= kern_recvmsg(linux_args
.s
, NULL
, &auio
, NULL
,
631 &linux_args
.flags
, res
);
636 struct linux_sendto_args
{
646 linux_sendto(struct linux_sendto_args
*args
, size_t *res
)
648 struct linux_sendto_args linux_args
;
649 struct thread
*td
= curthread
;
653 struct sockaddr
*sa
= NULL
;
657 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
662 error
= linux_getsockaddr(&sa
, linux_args
.to
,
669 * Check to see if the IP_HDRINCL option is set.
671 sopt
.sopt_dir
= SOPT_GET
;
672 sopt
.sopt_level
= IPPROTO_IP
;
673 sopt
.sopt_name
= IP_HDRINCL
;
674 sopt
.sopt_val
= &optval
;
675 sopt
.sopt_valsize
= sizeof(optval
);
678 if (kern_getsockopt(linux_args
.s
, &sopt
) != 0)
683 * IP_HDRINCL is not set. Package the message as usual.
685 aiov
.iov_base
= linux_args
.msg
;
686 aiov
.iov_len
= linux_args
.len
;
687 auio
.uio_iov
= &aiov
;
690 auio
.uio_resid
= linux_args
.len
;
691 auio
.uio_segflg
= UIO_USERSPACE
;
692 auio
.uio_rw
= UIO_WRITE
;
696 * IP_HDRINCL is set. We must convert the beginning of
697 * the packet header so we can feed it to the BSD kernel.
701 * Check that the packet header is long enough to contain
702 * the fields of interest. This relies on the fact that
703 * the fragment offset field comes after the length field.
705 if (linux_args
.len
< offsetof(struct ip
, ip_off
))
708 MALLOC(msg
, caddr_t
, linux_args
.len
, M_LINUX
, M_WAITOK
);
709 error
= copyin(linux_args
.msg
, msg
, linux_args
.len
);
713 /* Fix the ip_len and ip_off fields. */
714 ((struct ip
*)msg
)->ip_len
= linux_args
.len
;
715 ((struct ip
*)msg
)->ip_off
= ntohs(((struct ip
*)msg
)->ip_off
);
718 aiov
.iov_len
= linux_args
.len
;
719 auio
.uio_iov
= &aiov
;
722 auio
.uio_resid
= linux_args
.len
;
723 auio
.uio_segflg
= UIO_SYSSPACE
;
724 auio
.uio_rw
= UIO_WRITE
;
728 error
= kern_sendmsg(linux_args
.s
, sa
, &auio
, NULL
,
729 linux_args
.flags
, res
);
739 struct linux_recvfrom_args
{
744 struct sockaddr
*from
;
749 linux_recvfrom(struct linux_recvfrom_args
*args
, size_t *res
)
751 struct linux_recvfrom_args linux_args
;
752 struct thread
*td
= curthread
;
755 struct sockaddr
*sa
= NULL
;
756 int error
, fromlen
, flags
;
758 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
762 if (linux_args
.from
&& linux_args
.fromlen
) {
763 error
= copyin(linux_args
.fromlen
, &fromlen
, sizeof(fromlen
));
771 aiov
.iov_base
= linux_args
.buf
;
772 aiov
.iov_len
= linux_args
.len
;
773 auio
.uio_iov
= &aiov
;
776 auio
.uio_resid
= linux_args
.len
;
777 auio
.uio_segflg
= UIO_USERSPACE
;
778 auio
.uio_rw
= UIO_READ
;
781 flags
= linux_to_bsd_msg_flags(linux_args
.flags
);
783 error
= kern_recvmsg(linux_args
.s
, linux_args
.from
? &sa
: NULL
, &auio
,
786 if (error
== 0 && linux_args
.from
) {
788 fromlen
= MIN(fromlen
, sa
->sa_len
);
789 error
= linux_copyout_sockaddr(sa
, linux_args
.from
,
794 copyout(&fromlen
, linux_args
.fromlen
,
803 struct linux_sendmsg_args
{
810 linux_sendmsg(struct linux_sendmsg_args
*args
, size_t *res
)
812 struct linux_sendmsg_args linux_args
;
813 struct thread
*td
= curthread
;
816 struct iovec aiov
[UIO_SMALLIOV
], *iov
= NULL
;
817 struct sockaddr
*sa
= NULL
;
818 struct mbuf
*control
= NULL
;
821 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
825 error
= copyin(linux_args
.msg
, &msg
, sizeof(msg
));
830 * Conditionally copyin msg.msg_name.
833 error
= linux_getsockaddr(&sa
, msg
.msg_name
, msg
.msg_namelen
);
841 error
= iovec_copyin(msg
.msg_iov
, &iov
, aiov
, msg
.msg_iovlen
,
846 auio
.uio_iovcnt
= msg
.msg_iovlen
;
848 auio
.uio_segflg
= UIO_USERSPACE
;
849 auio
.uio_rw
= UIO_WRITE
;
853 * Conditionally copyin msg.msg_control.
855 if (msg
.msg_control
) {
856 if (msg
.msg_controllen
< sizeof(struct cmsghdr
) ||
857 msg
.msg_controllen
> MLEN
) {
861 control
= m_get(MB_WAIT
, MT_CONTROL
);
862 if (control
== NULL
) {
866 control
->m_len
= msg
.msg_controllen
;
867 error
= copyin(msg
.msg_control
, mtod(control
, caddr_t
),
874 * Linux and BSD both support SCM_RIGHTS. If a linux binary
875 * wants anything else with an option level of SOL_SOCKET,
876 * we don't support it.
878 if (mtod(control
, struct cmsghdr
*)->cmsg_level
==
880 mtod(control
, struct cmsghdr
*)->cmsg_type
!=
888 error
= kern_sendmsg(linux_args
.s
, sa
, &auio
, control
,
889 linux_args
.flags
, res
);
892 iovec_free(&iov
, aiov
);
899 struct linux_recvmsg_args
{
906 linux_recvmsg(struct linux_recvmsg_args
*args
, size_t *res
)
908 struct linux_recvmsg_args linux_args
;
909 struct thread
*td
= curthread
;
912 struct iovec aiov
[UIO_SMALLIOV
], *iov
= NULL
;
913 struct mbuf
*m
, *control
= NULL
;
914 struct sockaddr
*sa
= NULL
;
916 socklen_t
*ufromlenp
, *ucontrollenp
;
917 int error
, fromlen
, controllen
, len
, flags
, *uflagsp
;
919 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
923 error
= copyin(linux_args
.msg
, &msg
, sizeof(struct msghdr
));
927 if (msg
.msg_name
&& msg
.msg_namelen
< 0)
929 if (msg
.msg_control
&& msg
.msg_controllen
< 0)
932 ufromlenp
= (socklen_t
*)((caddr_t
)linux_args
.msg
+
933 offsetof(struct msghdr
, msg_namelen
));
934 ucontrollenp
= (socklen_t
*)((caddr_t
)linux_args
.msg
+
935 offsetof(struct msghdr
, msg_controllen
));
936 uflagsp
= (int *)((caddr_t
)linux_args
.msg
+
937 offsetof(struct msghdr
, msg_flags
));
942 error
= iovec_copyin(msg
.msg_iov
, &iov
, aiov
, msg
.msg_iovlen
,
947 auio
.uio_iovcnt
= msg
.msg_iovlen
;
949 auio
.uio_segflg
= UIO_USERSPACE
;
950 auio
.uio_rw
= UIO_READ
;
953 flags
= linux_to_bsd_msg_flags(linux_args
.flags
);
955 error
= kern_recvmsg(linux_args
.s
, msg
.msg_name
? &sa
: NULL
, &auio
,
956 msg
.msg_control
? &control
: NULL
, &flags
, res
);
959 * Copyout msg.msg_name and msg.msg_namelen.
961 if (error
== 0 && msg
.msg_name
) {
963 fromlen
= MIN(msg
.msg_namelen
, sa
->sa_len
);
964 error
= linux_copyout_sockaddr(sa
, msg
.msg_name
,
969 error
= copyout(&fromlen
, ufromlenp
,
974 * Copyout msg.msg_control and msg.msg_controllen.
976 if (error
== 0 && msg
.msg_control
) {
978 * Linux and BSD both support SCM_RIGHTS. If a linux binary
979 * wants anything else with an option level of SOL_SOCKET,
980 * we don't support it.
982 if (mtod((struct mbuf
*)msg
.msg_control
,
983 struct cmsghdr
*)->cmsg_level
== SOL_SOCKET
&&
984 mtod((struct mbuf
*)msg
.msg_control
,
985 struct cmsghdr
*)->cmsg_type
!= SCM_RIGHTS
) {
990 len
= msg
.msg_controllen
;
992 ctlbuf
= (caddr_t
)msg
.msg_control
;
994 while (m
&& len
> 0) {
997 if (len
>= m
->m_len
) {
1000 msg
.msg_flags
|= MSG_CTRUNC
;
1004 error
= copyout(mtod(m
, caddr_t
), ctlbuf
,
1013 controllen
= ctlbuf
- (caddr_t
)msg
.msg_control
;
1014 error
= copyout(&controllen
, ucontrollenp
,
1015 sizeof(*ucontrollenp
));
1019 error
= copyout(&flags
, uflagsp
, sizeof(*uflagsp
));
1024 iovec_free(&iov
, aiov
);
1030 struct linux_shutdown_args
{
1036 linux_shutdown(struct linux_shutdown_args
*args
, int *res
)
1038 struct linux_shutdown_args linux_args
;
1041 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
1045 error
= kern_shutdown(linux_args
.s
, linux_args
.how
);
1050 struct linux_setsockopt_args
{
1059 linux_setsockopt(struct linux_setsockopt_args
*args
, int *res
)
1061 struct linux_setsockopt_args linux_args
;
1062 struct thread
*td
= curthread
;
1063 struct sockopt sopt
;
1064 int error
, name
, level
;
1066 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
1070 level
= linux_to_bsd_sockopt_level(linux_args
.level
);
1073 name
= linux_to_bsd_so_sockopt(linux_args
.optname
);
1076 name
= linux_to_bsd_ip_sockopt(linux_args
.optname
);
1079 /* Linux TCP option values match BSD's */
1080 name
= linux_args
.optname
;
1089 sopt
.sopt_dir
= SOPT_SET
;
1090 sopt
.sopt_level
= level
;
1091 sopt
.sopt_name
= name
;
1092 sopt
.sopt_valsize
= linux_args
.optlen
;
1095 if (sopt
.sopt_valsize
< 0 || sopt
.sopt_valsize
> SOMAXOPT_SIZE
)
1098 if (linux_args
.optval
) {
1099 sopt
.sopt_val
= kmalloc(sopt
.sopt_valsize
, M_TEMP
, M_WAITOK
);
1100 error
= copyin(linux_args
.optval
, sopt
.sopt_val
, sopt
.sopt_valsize
);
1104 sopt
.sopt_val
= NULL
;
1106 error
= kern_setsockopt(linux_args
.s
, &sopt
);
1109 if (linux_args
.optval
)
1110 error
= copyout(sopt
.sopt_val
, linux_args
.optval
,
1113 if (linux_args
.optval
)
1114 kfree(sopt
.sopt_val
, M_TEMP
);
1118 struct linux_getsockopt_args
{
1127 linux_getsockopt(struct linux_getsockopt_args
*args
, int *res
)
1129 struct linux_getsockopt_args linux_args
;
1130 struct thread
*td
= curthread
;
1131 struct sockopt sopt
;
1132 int error
, name
, valsize
, level
;
1134 error
= copyin(args
, &linux_args
, sizeof(linux_args
));
1138 if (linux_args
.optval
) {
1139 error
= copyin(linux_args
.optlen
, &valsize
, sizeof(valsize
));
1142 if (valsize
< 0 || valsize
> SOMAXOPT_SIZE
)
1148 level
= linux_to_bsd_sockopt_level(linux_args
.level
);
1151 name
= linux_to_bsd_so_sockopt(linux_args
.optname
);
1154 name
= linux_to_bsd_ip_sockopt(linux_args
.optname
);
1157 /* Linux TCP option values match BSD's */
1158 name
= linux_args
.optname
;
1167 sopt
.sopt_dir
= SOPT_GET
;
1168 sopt
.sopt_level
= level
;
1169 sopt
.sopt_name
= name
;
1170 sopt
.sopt_valsize
= valsize
;
1173 if (linux_args
.optval
) {
1174 sopt
.sopt_val
= kmalloc(sopt
.sopt_valsize
, M_TEMP
, M_WAITOK
);
1175 error
= copyin(linux_args
.optval
, sopt
.sopt_val
, sopt
.sopt_valsize
);
1179 sopt
.sopt_val
= NULL
;
1181 error
= kern_getsockopt(linux_args
.s
, &sopt
);
1184 valsize
= sopt
.sopt_valsize
;
1185 error
= copyout(&valsize
, linux_args
.optlen
, sizeof(valsize
));
1188 if (linux_args
.optval
)
1189 error
= copyout(sopt
.sopt_val
, linux_args
.optval
, sopt
.sopt_valsize
);
1191 if (linux_args
.optval
)
1192 kfree(sopt
.sopt_val
, M_TEMP
);
1200 sys_linux_socketcall(struct linux_socketcall_args
*args
)
1202 void *arg
= (void *)args
->args
;
1206 switch (args
->what
) {
1208 return (linux_socket(arg
, &args
->sysmsg_result
));
1210 return (linux_bind(arg
, &args
->sysmsg_result
));
1212 return (linux_connect(arg
, &args
->sysmsg_result
));
1214 return (linux_listen(arg
, &args
->sysmsg_result
));
1216 return (linux_accept(arg
, &args
->sysmsg_result
));
1217 case LINUX_GETSOCKNAME
:
1218 return (linux_getsockname(arg
, &args
->sysmsg_result
));
1219 case LINUX_GETPEERNAME
:
1220 return (linux_getpeername(arg
, &args
->sysmsg_result
));
1221 case LINUX_SOCKETPAIR
:
1222 return (linux_socketpair(arg
, &args
->sysmsg_result
));
1224 return (linux_send(arg
, &args
->sysmsg_szresult
));
1226 return (linux_recv(arg
, &args
->sysmsg_szresult
));
1228 return (linux_sendto(arg
, &args
->sysmsg_szresult
));
1229 case LINUX_RECVFROM
:
1230 return (linux_recvfrom(arg
, &args
->sysmsg_szresult
));
1231 case LINUX_SHUTDOWN
:
1232 return (linux_shutdown(arg
, &args
->sysmsg_result
));
1233 case LINUX_SETSOCKOPT
:
1234 return (linux_setsockopt(arg
, &args
->sysmsg_result
));
1235 case LINUX_GETSOCKOPT
:
1236 return (linux_getsockopt(arg
, &args
->sysmsg_result
));
1238 return (linux_sendmsg(arg
, &args
->sysmsg_szresult
));
1240 return (linux_recvmsg(arg
, &args
->sysmsg_szresult
));
1244 uprintf("LINUX: 'socket' typ=%d not implemented\n", args
->what
);