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.12 2003/10/04 02:12:51 daver Exp $
32 /* XXX we use functions that might not exist. */
33 #include "opt_compat.h"
36 #error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
39 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/sysproto.h>
43 #include <sys/fcntl.h>
45 #include <sys/kern_syscall.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
49 #include <sys/malloc.h>
52 #include <netinet/in.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/ip.h>
56 #include <arch_linux/linux.h>
57 #include <arch_linux/linux_proto.h>
58 #include "linux_socket.h"
59 #include "linux_util.h"
62 * Copyin a sockaddr structure provided by a Linux binary. Linux uses
63 * the 4.3BSD sockaddr structure which has no sa_len field. We must
64 * pass 4.4BSD sockaddr structures when we call native functions in the
65 * BSD kernel. This function does the conversion for us.
67 * Also, our socket calls require the sockaddr structure length to agree
68 * with the address family. Linux does not, so we must force it.
70 * This function should only need to be called from linux_connect()
74 linux_getsockaddr(struct sockaddr **namp, struct sockaddr *uaddr, size_t len)
77 uint16_t family; /* XXX: must match Linux sockaddr */
83 if (len > SOCK_MAXADDRLEN)
85 error = copyin(uaddr, &family, sizeof(family));
90 * Force the sa_len field to match the address family.
94 sa_len = sizeof(struct sockaddr_in);
97 sa_len = sizeof(struct sockaddr_in6);
101 * This is the default behavior of the old
102 * linux_to_bsd_namelen() function. NOTE! The
103 * minimum length we allocate must cover sa->sa_len and
106 sa_len = offsetof(struct sockaddr, sa_data[0]);
112 MALLOC(sa, struct sockaddr *, sa_len, M_SONAME, M_WAITOK);
113 error = copyin(uaddr, sa, sa_len);
118 * Convert to the 4.4BSD sockaddr structure.
120 sa->sa_family = *(sa_family_t *)sa;
129 * Transform a 4.4BSD sockaddr structure into a Linux sockaddr structure
130 * and copy it out to a user address.
133 linux_copyout_sockaddr(struct sockaddr *sa, struct sockaddr *uaddr, int sa_len)
137 if (sa_len < (int)sizeof(u_short))
140 *(u_short *)sa = sa->sa_family;
141 error = copyout(sa, uaddr, sa_len);
148 linux_to_bsd_domain(int domain)
152 case LINUX_AF_UNSPEC:
162 case LINUX_AF_APPLETALK:
163 return (AF_APPLETALK);
169 linux_to_bsd_sockopt_level(int level)
173 case LINUX_SOL_SOCKET:
180 linux_to_bsd_ip_sockopt(int opt)
188 case LINUX_IP_OPTIONS:
190 case LINUX_IP_MULTICAST_IF:
191 return (IP_MULTICAST_IF);
192 case LINUX_IP_MULTICAST_TTL:
193 return (IP_MULTICAST_TTL);
194 case LINUX_IP_MULTICAST_LOOP:
195 return (IP_MULTICAST_LOOP);
196 case LINUX_IP_ADD_MEMBERSHIP:
197 return (IP_ADD_MEMBERSHIP);
198 case LINUX_IP_DROP_MEMBERSHIP:
199 return (IP_DROP_MEMBERSHIP);
200 case LINUX_IP_HDRINCL:
207 linux_to_bsd_so_sockopt(int opt)
213 case LINUX_SO_REUSEADDR:
214 return (SO_REUSEADDR);
219 case LINUX_SO_DONTROUTE:
220 return (SO_DONTROUTE);
221 case LINUX_SO_BROADCAST:
222 return (SO_BROADCAST);
223 case LINUX_SO_SNDBUF:
225 case LINUX_SO_RCVBUF:
227 case LINUX_SO_KEEPALIVE:
228 return (SO_KEEPALIVE);
229 case LINUX_SO_OOBINLINE:
230 return (SO_OOBINLINE);
231 case LINUX_SO_LINGER:
238 linux_to_bsd_msg_flags(int flags)
242 if (flags & LINUX_MSG_OOB)
243 ret_flags |= MSG_OOB;
244 if (flags & LINUX_MSG_PEEK)
245 ret_flags |= MSG_PEEK;
246 if (flags & LINUX_MSG_DONTROUTE)
247 ret_flags |= MSG_DONTROUTE;
248 if (flags & LINUX_MSG_CTRUNC)
249 ret_flags |= MSG_CTRUNC;
250 if (flags & LINUX_MSG_TRUNC)
251 ret_flags |= MSG_TRUNC;
252 if (flags & LINUX_MSG_DONTWAIT)
253 ret_flags |= MSG_DONTWAIT;
254 if (flags & LINUX_MSG_EOR)
255 ret_flags |= MSG_EOR;
256 if (flags & LINUX_MSG_WAITALL)
257 ret_flags |= MSG_WAITALL;
258 #if 0 /* not handled */
259 if (flags & LINUX_MSG_PROXY)
261 if (flags & LINUX_MSG_FIN)
263 if (flags & LINUX_MSG_SYN)
265 if (flags & LINUX_MSG_CONFIRM)
267 if (flags & LINUX_MSG_RST)
269 if (flags & LINUX_MSG_ERRQUEUE)
271 if (flags & LINUX_MSG_NOSIGNAL)
277 struct linux_socket_args {
284 linux_socket(struct linux_socket_args *args, int *res)
286 struct linux_socket_args linux_args;
287 struct socket_args bsd_args;
291 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
294 bsd_args.sysmsg_result = 0;
295 bsd_args.protocol = linux_args.protocol;
296 bsd_args.type = linux_args.type;
297 bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
298 if (bsd_args.domain == -1)
301 retval_socket = socket(&bsd_args);
302 /* Copy back the return value from socket() */
303 *res = bsd_args.sysmsg_result;
304 if (bsd_args.type == SOCK_RAW
305 && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)
306 && bsd_args.domain == AF_INET
307 && retval_socket >= 0) {
308 /* It's a raw IP socket: set the IP_HDRINCL option. */
309 struct setsockopt_args /* {
315 } */ bsd_setsockopt_args;
319 sg = stackgap_init();
320 hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl));
322 bsd_setsockopt_args.s = bsd_args.sysmsg_result;
323 bsd_setsockopt_args.level = IPPROTO_IP;
324 bsd_setsockopt_args.name = IP_HDRINCL;
325 bsd_setsockopt_args.val = (caddr_t)hdrincl;
326 bsd_setsockopt_args.valsize = sizeof(*hdrincl);
327 /* We ignore any error returned by setsockopt() */
328 setsockopt(&bsd_setsockopt_args);
331 return (retval_socket);
334 struct linux_bind_args {
336 struct sockaddr *name;
341 linux_bind(struct linux_bind_args *args, int *res)
343 struct linux_bind_args linux_args;
347 error = copyin(args, &linux_args, sizeof(linux_args));
350 error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
354 error = kern_bind(linux_args.s, sa);
360 struct linux_connect_args {
362 struct sockaddr * name;
365 int linux_connect(struct linux_connect_args *, int *res);
366 #endif /* !__alpha__*/
369 linux_connect(struct linux_connect_args *args, int *res)
371 struct thread *td = curthread; /* XXX */
372 struct proc *p = td->td_proc;
373 struct linux_connect_args linux_args;
381 error = copyin(args, &linux_args, sizeof(linux_args));
384 error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
388 error = kern_connect(linux_args.s, sa);
391 if (error != EISCONN)
395 * Linux doesn't return EISCONN the first time it occurs,
396 * when on a non-blocking socket. Instead it returns the
397 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
399 error = holdsock(p->p_fd, linux_args.s, &fp);
403 if (fp->f_flag & FNONBLOCK) {
404 so = (struct socket *)fp->f_data;
405 if (so->so_emuldata == 0)
406 error = so->so_error;
407 so->so_emuldata = (void *)1;
415 struct linux_listen_args {
421 linux_listen(struct linux_listen_args *args, int *res)
423 struct linux_listen_args linux_args;
426 error = copyin(args, &linux_args, sizeof(linux_args));
430 error = kern_listen(linux_args.s, linux_args.backlog);
435 struct linux_accept_args {
437 struct sockaddr *addr;
442 linux_accept(struct linux_accept_args *args, int *res)
444 struct linux_accept_args linux_args;
445 struct fcntl_args /* {
450 struct sockaddr *sa = NULL;
453 error = copyin(args, &linux_args, sizeof(linux_args));
457 if (linux_args.addr) {
458 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
462 error = kern_accept(linux_args.s, &sa, &sa_len, res);
466 * Return a namelen of zero for older code which
467 * might ignore the return value from accept().
470 copyout(&sa_len, linux_args.namelen,
471 sizeof(*linux_args.namelen));
473 error = linux_copyout_sockaddr(sa, linux_args.addr,
476 error = copyout(&sa_len, linux_args.namelen,
477 sizeof(*linux_args.namelen));
483 error = kern_accept(linux_args.s, NULL, 0, res);
490 * linux appears not to copy flags from the parent socket to the
491 * accepted one, so we must clear the flags in the new descriptor.
492 * Ignore any errors, because we already have an open fd.
495 f_args.cmd = F_SETFL;
497 (void)fcntl(&f_args);
501 struct linux_getsockname_args {
503 struct sockaddr *addr;
508 linux_getsockname(struct linux_getsockname_args *args, int *res)
510 struct linux_getsockname_args linux_args;
511 struct sockaddr *sa = NULL;
514 error = copyin(args, &linux_args, sizeof(linux_args));
517 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
521 error = kern_getsockname(linux_args.s, &sa, &sa_len);
524 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
526 error = copyout(&sa_len, linux_args.namelen,
527 sizeof(*linux_args.namelen));
533 struct linux_getpeername_args {
535 struct sockaddr *addr;
540 linux_getpeername(struct linux_getpeername_args *args, int *res)
542 struct linux_getpeername_args linux_args;
543 struct sockaddr *sa = NULL;
546 error = copyin(args, &linux_args, sizeof(linux_args));
549 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
553 error = kern_getpeername(linux_args.s, &sa, &sa_len);
556 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
558 error = copyout(&sa_len, linux_args.namelen,
559 sizeof(*linux_args.namelen));
565 struct linux_socketpair_args {
573 linux_socketpair(struct linux_socketpair_args *args, int *res)
575 struct linux_socketpair_args linux_args;
576 int error, domain, sockv[2];
578 error = copyin(args, &linux_args, sizeof(linux_args));
582 domain = linux_to_bsd_domain(linux_args.domain);
585 error = kern_socketpair(domain, linux_args.type, linux_args.protocol,
589 error = copyout(sockv, linux_args.rsv, sizeof(sockv));
593 struct linux_send_args {
601 linux_send(struct linux_send_args *args, int *res)
603 struct linux_send_args linux_args;
604 struct thread *td = curthread;
609 error = copyin(args, &linux_args, sizeof(linux_args));
613 aiov.iov_base = linux_args.msg;
614 aiov.iov_len = linux_args.len;
615 auio.uio_iov = &aiov;
618 auio.uio_resid = linux_args.len;
619 auio.uio_segflg = UIO_USERSPACE;
620 auio.uio_rw = UIO_WRITE;
623 error = kern_sendmsg(linux_args.s, NULL, &auio, NULL,
624 linux_args.flags, res);
629 struct linux_recv_args {
637 linux_recv(struct linux_recv_args *args, int *res)
639 struct linux_recv_args linux_args;
640 struct thread *td = curthread;
645 error = copyin(args, &linux_args, sizeof(linux_args));
649 aiov.iov_base = linux_args.msg;
650 aiov.iov_len = linux_args.len;
651 auio.uio_iov = &aiov;
654 auio.uio_resid = linux_args.len;
655 auio.uio_segflg = UIO_USERSPACE;
656 auio.uio_rw = UIO_READ;
659 error = kern_recvmsg(linux_args.s, NULL, &auio, NULL,
660 &linux_args.flags, res);
665 struct linux_sendto_args {
675 linux_sendto(struct linux_sendto_args *args, int *res)
677 struct linux_sendto_args linux_args;
678 struct thread *td = curthread;
682 struct sockaddr *sa = NULL;
686 error = copyin(args, &linux_args, sizeof(linux_args));
691 error = linux_getsockaddr(&sa, linux_args.to,
698 * Check to see if the IP_HDRINCL option is set.
700 sopt.sopt_dir = SOPT_GET;
701 sopt.sopt_level = IPPROTO_IP;
702 sopt.sopt_name = IP_HDRINCL;
703 sopt.sopt_val = &optval;
704 sopt.sopt_valsize = sizeof(optval);
707 error = kern_getsockopt(linux_args.s, &sopt);
713 * IP_HDRINCL is not set. Package the message as usual.
715 aiov.iov_base = linux_args.msg;
716 aiov.iov_len = linux_args.len;
717 auio.uio_iov = &aiov;
720 auio.uio_resid = linux_args.len;
721 auio.uio_segflg = UIO_USERSPACE;
722 auio.uio_rw = UIO_WRITE;
726 * IP_HDRINCL is set. We must convert the beginning of
727 * the packet header so we can feed it to the BSD kernel.
731 * Check that the packet header is long enough to contain
732 * the fields of interest. This relies on the fact that
733 * the fragment offset field comes after the length field.
735 if (linux_args.len < offsetof(struct ip, ip_off))
738 MALLOC(msg, caddr_t, linux_args.len, M_LINUX, M_WAITOK);
739 error = copyin(linux_args.msg, msg, linux_args.len);
743 /* Fix the ip_len and ip_off fields. */
744 ((struct ip *)msg)->ip_len = linux_args.len;
745 ((struct ip *)msg)->ip_off = ntohs(((struct ip *)msg)->ip_off);
748 aiov.iov_len = linux_args.len;
749 auio.uio_iov = &aiov;
752 auio.uio_resid = linux_args.len;
753 auio.uio_segflg = UIO_SYSSPACE;
754 auio.uio_rw = UIO_WRITE;
758 error = kern_sendmsg(linux_args.s, sa, &auio, NULL, linux_args.flags,
769 struct linux_recvfrom_args {
774 struct sockaddr *from;
779 linux_recvfrom(struct linux_recvfrom_args *args, int *res)
781 struct linux_recvfrom_args linux_args;
782 struct thread *td = curthread;
785 struct sockaddr *sa = NULL;
786 int error, fromlen, flags;
788 error = copyin(args, &linux_args, sizeof(linux_args));
792 if (linux_args.from && linux_args.fromlen) {
793 error = copyin(linux_args.fromlen, &fromlen, sizeof(fromlen));
801 aiov.iov_base = linux_args.buf;
802 aiov.iov_len = linux_args.len;
803 auio.uio_iov = &aiov;
806 auio.uio_resid = linux_args.len;
807 auio.uio_segflg = UIO_USERSPACE;
808 auio.uio_rw = UIO_READ;
811 flags = linux_to_bsd_msg_flags(linux_args.flags);
813 error = kern_recvmsg(linux_args.s, linux_args.from ? &sa : NULL, &auio,
816 if (error == 0 && linux_args.from) {
817 fromlen = MIN(fromlen, sa->sa_len);
818 error = linux_copyout_sockaddr(sa, linux_args.from, fromlen);
820 copyout(&fromlen, linux_args.fromlen,
829 struct linux_sendmsg_args {
836 linux_sendmsg(struct linux_sendmsg_args *args, int *res)
838 struct linux_sendmsg_args linux_args;
839 struct thread *td = curthread;
842 struct iovec aiov[UIO_SMALLIOV], *iov = NULL, *iovp;
843 struct sockaddr *sa = NULL;
844 struct mbuf *control = NULL;
847 error = copyin(args, &linux_args, sizeof(linux_args));
851 error = copyin(linux_args.msg, &msg, sizeof(msg));
856 * Conditionally copyin msg.msg_name.
859 error = linux_getsockaddr(&sa, msg.msg_name, msg.msg_namelen);
867 if (msg.msg_iovlen >= UIO_MAXIOV) {
871 if (msg.msg_iovlen >= UIO_SMALLIOV) {
872 MALLOC(iov, struct iovec *,
873 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
877 error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof(struct iovec));
881 auio.uio_iovcnt = msg.msg_iovlen;
884 for (i = 0, iovp = auio.uio_iov; i < msg.msg_iovlen; i++, iovp++) {
885 auio.uio_resid += iovp->iov_len;
886 if (auio.uio_resid < 0) {
891 auio.uio_segflg = UIO_USERSPACE;
892 auio.uio_rw = UIO_WRITE;
896 * Conditionally copyin msg.msg_control.
898 if (msg.msg_control) {
899 if (msg.msg_controllen < sizeof(struct cmsghdr) ||
900 msg.msg_controllen > MLEN) {
904 control = m_get(M_WAIT, MT_CONTROL);
905 if (control == NULL) {
909 control->m_len = msg.msg_controllen;
910 error = copyin(msg.msg_control, mtod(control, caddr_t),
917 * Linux and BSD both support SCM_RIGHTS. If a linux binary
918 * wants anything else with an option level of SOL_SOCKET,
919 * we don't support it.
921 if (mtod(control, struct cmsghdr *)->cmsg_level ==
923 mtod(control, struct cmsghdr *)->cmsg_type !=
931 error = kern_sendmsg(linux_args.s, sa, &auio, control,
932 linux_args.flags, res);
942 struct linux_recvmsg_args {
949 linux_recvmsg(struct linux_recvmsg_args *args, int *res)
951 struct linux_recvmsg_args linux_args;
952 struct thread *td = curthread;
955 struct iovec aiov[UIO_SMALLIOV], *iov = NULL, *iovp;
956 struct mbuf *m, *control;
957 struct sockaddr *sa = NULL;
959 socklen_t *ufromlenp, *ucontrollenp;
960 int error, fromlen, controllen, len, i, flags, *uflagsp;
962 error = copyin(args, &linux_args, sizeof(linux_args));
966 error = copyin(linux_args.msg, &msg, sizeof(struct msghdr));
970 if (msg.msg_name && msg.msg_namelen < 0)
972 if (msg.msg_control && msg.msg_controllen < 0)
975 ufromlenp = (socklen_t *)((caddr_t)linux_args.msg +
976 offsetof(struct msghdr, msg_namelen));
977 ucontrollenp = (socklen_t *)((caddr_t)linux_args.msg +
978 offsetof(struct msghdr, msg_controllen));
979 uflagsp = (int *)((caddr_t)linux_args.msg +
980 offsetof(struct msghdr, msg_flags));
985 if (msg.msg_iovlen >= UIO_MAXIOV)
987 if (msg.msg_iovlen >= UIO_SMALLIOV) {
988 MALLOC(iov, struct iovec *,
989 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
993 error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof(struct iovec));
997 auio.uio_iovcnt = msg.msg_iovlen;
1000 for (i = 0, iovp = auio.uio_iov; i < msg.msg_iovlen; i++, iovp++) {
1001 auio.uio_resid += iovp->iov_len;
1002 if (auio.uio_resid < 0) {
1007 auio.uio_segflg = UIO_USERSPACE;
1008 auio.uio_rw = UIO_READ;
1011 flags = linux_to_bsd_msg_flags(linux_args.flags);
1013 error = kern_recvmsg(linux_args.s, msg.msg_name ? &sa : NULL, &auio,
1014 msg.msg_control ? &control : NULL, &flags, res);
1017 * Copyout msg.msg_name and msg.msg_namelen.
1019 if (error == 0 && msg.msg_name) {
1020 fromlen = MIN(msg.msg_namelen, sa->sa_len);
1021 error = linux_copyout_sockaddr(sa, msg.msg_name, fromlen);
1023 error = copyout(&fromlen, ufromlenp,
1024 sizeof(*ufromlenp));
1028 * Copyout msg.msg_control and msg.msg_controllen.
1030 if (error == 0 && msg.msg_control) {
1032 * Linux and BSD both support SCM_RIGHTS. If a linux binary
1033 * wants anything else with an option level of SOL_SOCKET,
1034 * we don't support it.
1036 if (mtod((struct mbuf *)msg.msg_control,
1037 struct cmsghdr *)->cmsg_level == SOL_SOCKET &&
1038 mtod((struct mbuf *)msg.msg_control,
1039 struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
1044 len = msg.msg_controllen;
1046 ctlbuf = (caddr_t)msg.msg_control;
1048 while (m && len > 0) {
1049 unsigned int tocopy;
1051 if (len >= m->m_len) {
1054 msg.msg_flags |= MSG_CTRUNC;
1058 error = copyout(mtod(m, caddr_t), ctlbuf,
1067 controllen = ctlbuf - (caddr_t)msg.msg_control;
1068 error = copyout(&controllen, ucontrollenp,
1069 sizeof(*ucontrollenp));
1073 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
1085 struct linux_shutdown_args {
1091 linux_shutdown(struct linux_shutdown_args *args, int *res)
1093 struct linux_shutdown_args linux_args;
1094 struct shutdown_args /* {
1100 if ((error = copyin(args, &linux_args, sizeof(linux_args))))
1103 bsd_args.sysmsg_result = 0;
1104 bsd_args.s = linux_args.s;
1105 bsd_args.how = linux_args.how;
1106 error = shutdown(&bsd_args);
1107 *res = bsd_args.sysmsg_result;
1111 struct linux_setsockopt_args {
1120 linux_setsockopt(struct linux_setsockopt_args *args, int *res)
1122 struct linux_setsockopt_args linux_args;
1123 struct thread *td = curthread;
1124 struct sockopt sopt;
1125 int error, name, level;
1127 error = copyin(args, &linux_args, sizeof(linux_args));
1131 level = linux_to_bsd_sockopt_level(linux_args.level);
1134 name = linux_to_bsd_so_sockopt(linux_args.optname);
1137 name = linux_to_bsd_ip_sockopt(linux_args.optname);
1140 /* Linux TCP option values match BSD's */
1141 name = linux_args.optname;
1150 sopt.sopt_dir = SOPT_SET;
1151 sopt.sopt_level = level;
1152 sopt.sopt_name = name;
1153 sopt.sopt_val = linux_args.optval;
1154 sopt.sopt_valsize = linux_args.optlen;
1157 error = kern_setsockopt(linux_args.s, &sopt);
1161 struct linux_getsockopt_args {
1170 linux_getsockopt(struct linux_getsockopt_args *args, int *res)
1172 struct linux_getsockopt_args linux_args;
1173 struct thread *td = curthread;
1174 struct sockopt sopt;
1175 int error, name, valsize, level;
1177 error = copyin(args, &linux_args, sizeof(linux_args));
1181 if (linux_args.optval) {
1182 error = copyin(linux_args.optlen, &valsize, sizeof(valsize));
1191 level = linux_to_bsd_sockopt_level(linux_args.level);
1194 name = linux_to_bsd_so_sockopt(linux_args.optname);
1197 name = linux_to_bsd_ip_sockopt(linux_args.optname);
1200 /* Linux TCP option values match BSD's */
1201 name = linux_args.optname;
1210 sopt.sopt_dir = SOPT_GET;
1211 sopt.sopt_level = level;
1212 sopt.sopt_name = name;
1213 sopt.sopt_val = linux_args.optval;
1214 sopt.sopt_valsize = valsize;
1217 error = kern_getsockopt(linux_args.s, &sopt);
1219 valsize = sopt.sopt_valsize;
1220 error = copyout(&valsize, linux_args.optlen, sizeof(valsize));
1226 linux_socketcall(struct linux_socketcall_args *args)
1228 void *arg = (void *)args->args;
1230 switch (args->what) {
1232 return (linux_socket(arg, &args->sysmsg_result));
1234 return (linux_bind(arg, &args->sysmsg_result));
1236 return (linux_connect(arg, &args->sysmsg_result));
1238 return (linux_listen(arg, &args->sysmsg_result));
1240 return (linux_accept(arg, &args->sysmsg_result));
1241 case LINUX_GETSOCKNAME:
1242 return (linux_getsockname(arg, &args->sysmsg_result));
1243 case LINUX_GETPEERNAME:
1244 return (linux_getpeername(arg, &args->sysmsg_result));
1245 case LINUX_SOCKETPAIR:
1246 return (linux_socketpair(arg, &args->sysmsg_result));
1248 return (linux_send(arg, &args->sysmsg_result));
1250 return (linux_recv(arg, &args->sysmsg_result));
1252 return (linux_sendto(arg, &args->sysmsg_result));
1253 case LINUX_RECVFROM:
1254 return (linux_recvfrom(arg, &args->sysmsg_result));
1255 case LINUX_SHUTDOWN:
1256 return (linux_shutdown(arg, &args->sysmsg_result));
1257 case LINUX_SETSOCKOPT:
1258 return (linux_setsockopt(arg, &args->sysmsg_result));
1259 case LINUX_GETSOCKOPT:
1260 return (linux_getsockopt(arg, &args->sysmsg_result));
1262 return (linux_sendmsg(arg, &args->sysmsg_result));
1264 return (linux_recvmsg(arg, &args->sysmsg_result));
1267 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
1270 #endif /*!__alpha__*/