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.18 2004/06/02 14:42:57 eirikn 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 <netinet/in.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/ip.h>
49 #include <arch_linux/linux.h>
50 #include <arch_linux/linux_proto.h>
51 #include "linux_socket.h"
52 #include "linux_util.h"
55 * Copyin a sockaddr structure provided by a Linux binary. Linux uses
56 * the 4.3BSD sockaddr structure which has no sa_len field. We must
57 * pass 4.4BSD sockaddr structures when we call native functions in the
58 * BSD kernel. This function does the conversion for us.
60 * Also, our socket calls require the sockaddr structure length to agree
61 * with the address family. Linux does not, so we must force it.
63 * This function should only need to be called from linux_connect()
67 linux_getsockaddr(struct sockaddr **namp, struct sockaddr *uaddr, size_t len)
70 uint16_t family; /* XXX: must match Linux sockaddr */
76 if (len > SOCK_MAXADDRLEN)
78 error = copyin(uaddr, &family, sizeof(family));
83 * Force the sa_len field to match the address family.
87 sa_len = sizeof(struct sockaddr_in);
90 sa_len = sizeof(struct sockaddr_in6);
94 * This is the default behavior of the old
95 * linux_to_bsd_namelen() function. NOTE! The
96 * minimum length we allocate must cover sa->sa_len and
99 sa_len = offsetof(struct sockaddr, sa_data[0]);
105 MALLOC(sa, struct sockaddr *, sa_len, M_SONAME, M_WAITOK);
106 error = copyin(uaddr, sa, sa_len);
111 * Convert to the 4.4BSD sockaddr structure.
113 sa->sa_family = *(sa_family_t *)sa;
122 * Transform a 4.4BSD sockaddr structure into a Linux sockaddr structure
123 * and copy it out to a user address.
126 linux_copyout_sockaddr(struct sockaddr *sa, struct sockaddr *uaddr, int sa_len)
130 if (sa_len < (int)sizeof(u_short))
133 *(u_short *)sa = sa->sa_family;
134 error = copyout(sa, uaddr, sa_len);
141 linux_to_bsd_domain(int domain)
145 case LINUX_AF_UNSPEC:
155 case LINUX_AF_APPLETALK:
156 return (AF_APPLETALK);
162 linux_to_bsd_sockopt_level(int level)
166 case LINUX_SOL_SOCKET:
173 linux_to_bsd_ip_sockopt(int opt)
181 case LINUX_IP_OPTIONS:
183 case LINUX_IP_MULTICAST_IF:
184 return (IP_MULTICAST_IF);
185 case LINUX_IP_MULTICAST_TTL:
186 return (IP_MULTICAST_TTL);
187 case LINUX_IP_MULTICAST_LOOP:
188 return (IP_MULTICAST_LOOP);
189 case LINUX_IP_ADD_MEMBERSHIP:
190 return (IP_ADD_MEMBERSHIP);
191 case LINUX_IP_DROP_MEMBERSHIP:
192 return (IP_DROP_MEMBERSHIP);
193 case LINUX_IP_HDRINCL:
200 linux_to_bsd_so_sockopt(int opt)
206 case LINUX_SO_REUSEADDR:
207 return (SO_REUSEADDR);
212 case LINUX_SO_DONTROUTE:
213 return (SO_DONTROUTE);
214 case LINUX_SO_BROADCAST:
215 return (SO_BROADCAST);
216 case LINUX_SO_SNDBUF:
218 case LINUX_SO_RCVBUF:
220 case LINUX_SO_KEEPALIVE:
221 return (SO_KEEPALIVE);
222 case LINUX_SO_OOBINLINE:
223 return (SO_OOBINLINE);
224 case LINUX_SO_LINGER:
231 linux_to_bsd_msg_flags(int flags)
235 if (flags & LINUX_MSG_OOB)
236 ret_flags |= MSG_OOB;
237 if (flags & LINUX_MSG_PEEK)
238 ret_flags |= MSG_PEEK;
239 if (flags & LINUX_MSG_DONTROUTE)
240 ret_flags |= MSG_DONTROUTE;
241 if (flags & LINUX_MSG_CTRUNC)
242 ret_flags |= MSG_CTRUNC;
243 if (flags & LINUX_MSG_TRUNC)
244 ret_flags |= MSG_TRUNC;
245 if (flags & LINUX_MSG_DONTWAIT)
246 ret_flags |= MSG_DONTWAIT;
247 if (flags & LINUX_MSG_EOR)
248 ret_flags |= MSG_EOR;
249 if (flags & LINUX_MSG_WAITALL)
250 ret_flags |= MSG_WAITALL;
251 #if 0 /* not handled */
252 if (flags & LINUX_MSG_PROXY)
254 if (flags & LINUX_MSG_FIN)
256 if (flags & LINUX_MSG_SYN)
258 if (flags & LINUX_MSG_CONFIRM)
260 if (flags & LINUX_MSG_RST)
262 if (flags & LINUX_MSG_ERRQUEUE)
264 if (flags & LINUX_MSG_NOSIGNAL)
270 struct linux_socket_args {
277 linux_socket(struct linux_socket_args *args, int *res)
279 struct linux_socket_args linux_args;
281 int error, domain, optval;
283 error = copyin(args, &linux_args, sizeof(linux_args));
287 domain = linux_to_bsd_domain(linux_args.domain);
291 error = kern_socket(domain, linux_args.type, linux_args.protocol, res);
293 /* Copy back the return value from socket() */
294 if (error == 0 && linux_args.type == SOCK_RAW &&
295 (linux_args.protocol == IPPROTO_RAW || linux_args.protocol == 0) &&
296 linux_args.domain == AF_INET) {
297 /* It's a raw IP socket: set the IP_HDRINCL option. */
299 sopt.sopt_dir = SOPT_SET;
300 sopt.sopt_level = IPPROTO_IP;
301 sopt.sopt_name = IP_HDRINCL;
302 sopt.sopt_val = &optval;
303 sopt.sopt_valsize = sizeof(optval);
306 /* We ignore any error returned by setsockopt() */
307 kern_setsockopt(*res, &sopt);
313 struct linux_bind_args {
315 struct sockaddr *name;
320 linux_bind(struct linux_bind_args *args, int *res)
322 struct linux_bind_args linux_args;
326 error = copyin(args, &linux_args, sizeof(linux_args));
329 error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
333 error = kern_bind(linux_args.s, sa);
339 struct linux_connect_args {
341 struct sockaddr * name;
344 int linux_connect(struct linux_connect_args *, int *res);
345 #endif /* !__alpha__*/
348 linux_connect(struct linux_connect_args *args, int *res)
350 struct thread *td = curthread; /* XXX */
351 struct proc *p = td->td_proc;
352 struct linux_connect_args linux_args;
360 error = copyin(args, &linux_args, sizeof(linux_args));
363 error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen);
367 error = kern_connect(linux_args.s, sa);
370 if (error != EISCONN)
374 * Linux doesn't return EISCONN the first time it occurs,
375 * when on a non-blocking socket. Instead it returns the
376 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
378 error = holdsock(p->p_fd, linux_args.s, &fp);
382 if (fp->f_flag & FNONBLOCK) {
383 so = (struct socket *)fp->f_data;
384 if (so->so_emuldata == 0)
385 error = so->so_error;
386 so->so_emuldata = (void *)1;
394 struct linux_listen_args {
400 linux_listen(struct linux_listen_args *args, int *res)
402 struct linux_listen_args linux_args;
405 error = copyin(args, &linux_args, sizeof(linux_args));
409 error = kern_listen(linux_args.s, linux_args.backlog);
414 struct linux_accept_args {
416 struct sockaddr *addr;
421 linux_accept(struct linux_accept_args *args, int *res)
423 struct linux_accept_args linux_args;
424 struct sockaddr *sa = NULL;
425 union fcntl_dat dat = { 0 };
428 error = copyin(args, &linux_args, sizeof(linux_args));
432 if (linux_args.addr) {
433 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
437 error = kern_accept(linux_args.s, &sa, &sa_len, res);
441 * Return a namelen of zero for older code which
442 * might ignore the return value from accept().
445 copyout(&sa_len, linux_args.namelen,
446 sizeof(*linux_args.namelen));
448 error = linux_copyout_sockaddr(sa, linux_args.addr,
451 error = copyout(&sa_len, linux_args.namelen,
452 sizeof(*linux_args.namelen));
458 error = kern_accept(linux_args.s, NULL, 0, res);
465 * linux appears not to copy flags from the parent socket to the
466 * accepted one, so we must clear the flags in the new descriptor.
467 * Ignore any errors, because we already have an open fd.
469 kern_fcntl(*res, F_SETFL, &dat);
473 struct linux_getsockname_args {
475 struct sockaddr *addr;
480 linux_getsockname(struct linux_getsockname_args *args, int *res)
482 struct linux_getsockname_args linux_args;
483 struct sockaddr *sa = NULL;
487 error = copyin(args, &linux_args, sizeof(linux_args));
490 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
494 error = kern_getsockname(linux_args.s, &sa, &sa_len);
497 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
499 error = copyout(&sa_len, linux_args.namelen,
500 sizeof(*linux_args.namelen));
506 struct linux_getpeername_args {
508 struct sockaddr *addr;
513 linux_getpeername(struct linux_getpeername_args *args, int *res)
515 struct linux_getpeername_args linux_args;
516 struct sockaddr *sa = NULL;
519 error = copyin(args, &linux_args, sizeof(linux_args));
522 error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
526 error = kern_getpeername(linux_args.s, &sa, &sa_len);
529 error = linux_copyout_sockaddr(sa, linux_args.addr, sa_len);
531 error = copyout(&sa_len, linux_args.namelen,
532 sizeof(*linux_args.namelen));
538 struct linux_socketpair_args {
546 linux_socketpair(struct linux_socketpair_args *args, int *res)
548 struct linux_socketpair_args linux_args;
549 int error, domain, sockv[2];
551 error = copyin(args, &linux_args, sizeof(linux_args));
555 domain = linux_to_bsd_domain(linux_args.domain);
558 error = kern_socketpair(domain, linux_args.type, linux_args.protocol,
562 error = copyout(sockv, linux_args.rsv, sizeof(sockv));
566 struct linux_send_args {
574 linux_send(struct linux_send_args *args, int *res)
576 struct linux_send_args linux_args;
577 struct thread *td = curthread;
582 error = copyin(args, &linux_args, sizeof(linux_args));
586 aiov.iov_base = linux_args.msg;
587 aiov.iov_len = linux_args.len;
588 auio.uio_iov = &aiov;
591 auio.uio_resid = linux_args.len;
592 auio.uio_segflg = UIO_USERSPACE;
593 auio.uio_rw = UIO_WRITE;
596 error = kern_sendmsg(linux_args.s, NULL, &auio, NULL,
597 linux_args.flags, res);
602 struct linux_recv_args {
610 linux_recv(struct linux_recv_args *args, int *res)
612 struct linux_recv_args linux_args;
613 struct thread *td = curthread;
618 error = copyin(args, &linux_args, sizeof(linux_args));
622 aiov.iov_base = linux_args.msg;
623 aiov.iov_len = linux_args.len;
624 auio.uio_iov = &aiov;
627 auio.uio_resid = linux_args.len;
628 auio.uio_segflg = UIO_USERSPACE;
629 auio.uio_rw = UIO_READ;
632 error = kern_recvmsg(linux_args.s, NULL, &auio, NULL,
633 &linux_args.flags, res);
638 struct linux_sendto_args {
648 linux_sendto(struct linux_sendto_args *args, int *res)
650 struct linux_sendto_args linux_args;
651 struct thread *td = curthread;
655 struct sockaddr *sa = NULL;
659 error = copyin(args, &linux_args, sizeof(linux_args));
664 error = linux_getsockaddr(&sa, linux_args.to,
671 * Check to see if the IP_HDRINCL option is set.
673 sopt.sopt_dir = SOPT_GET;
674 sopt.sopt_level = IPPROTO_IP;
675 sopt.sopt_name = IP_HDRINCL;
676 sopt.sopt_val = &optval;
677 sopt.sopt_valsize = sizeof(optval);
680 if (kern_getsockopt(linux_args.s, &sopt) != 0)
685 * IP_HDRINCL is not set. Package the message as usual.
687 aiov.iov_base = linux_args.msg;
688 aiov.iov_len = linux_args.len;
689 auio.uio_iov = &aiov;
692 auio.uio_resid = linux_args.len;
693 auio.uio_segflg = UIO_USERSPACE;
694 auio.uio_rw = UIO_WRITE;
698 * IP_HDRINCL is set. We must convert the beginning of
699 * the packet header so we can feed it to the BSD kernel.
703 * Check that the packet header is long enough to contain
704 * the fields of interest. This relies on the fact that
705 * the fragment offset field comes after the length field.
707 if (linux_args.len < offsetof(struct ip, ip_off))
710 MALLOC(msg, caddr_t, linux_args.len, M_LINUX, M_WAITOK);
711 error = copyin(linux_args.msg, msg, linux_args.len);
715 /* Fix the ip_len and ip_off fields. */
716 ((struct ip *)msg)->ip_len = linux_args.len;
717 ((struct ip *)msg)->ip_off = ntohs(((struct ip *)msg)->ip_off);
720 aiov.iov_len = linux_args.len;
721 auio.uio_iov = &aiov;
724 auio.uio_resid = linux_args.len;
725 auio.uio_segflg = UIO_SYSSPACE;
726 auio.uio_rw = UIO_WRITE;
730 error = kern_sendmsg(linux_args.s, sa, &auio, NULL, linux_args.flags,
741 struct linux_recvfrom_args {
746 struct sockaddr *from;
751 linux_recvfrom(struct linux_recvfrom_args *args, int *res)
753 struct linux_recvfrom_args linux_args;
754 struct thread *td = curthread;
757 struct sockaddr *sa = NULL;
758 int error, fromlen, flags;
760 error = copyin(args, &linux_args, sizeof(linux_args));
764 if (linux_args.from && linux_args.fromlen) {
765 error = copyin(linux_args.fromlen, &fromlen, sizeof(fromlen));
773 aiov.iov_base = linux_args.buf;
774 aiov.iov_len = linux_args.len;
775 auio.uio_iov = &aiov;
778 auio.uio_resid = linux_args.len;
779 auio.uio_segflg = UIO_USERSPACE;
780 auio.uio_rw = UIO_READ;
783 flags = linux_to_bsd_msg_flags(linux_args.flags);
785 error = kern_recvmsg(linux_args.s, linux_args.from ? &sa : NULL, &auio,
788 if (error == 0 && linux_args.from) {
789 fromlen = MIN(fromlen, sa->sa_len);
790 error = linux_copyout_sockaddr(sa, linux_args.from, fromlen);
792 copyout(&fromlen, linux_args.fromlen,
801 struct linux_sendmsg_args {
808 linux_sendmsg(struct linux_sendmsg_args *args, int *res)
810 struct linux_sendmsg_args linux_args;
811 struct thread *td = curthread;
814 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
815 struct sockaddr *sa = NULL;
816 struct mbuf *control = NULL;
819 error = copyin(args, &linux_args, sizeof(linux_args));
823 error = copyin(linux_args.msg, &msg, sizeof(msg));
828 * Conditionally copyin msg.msg_name.
831 error = linux_getsockaddr(&sa, msg.msg_name, msg.msg_namelen);
839 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
844 auio.uio_iovcnt = msg.msg_iovlen;
846 auio.uio_segflg = UIO_USERSPACE;
847 auio.uio_rw = UIO_WRITE;
851 * Conditionally copyin msg.msg_control.
853 if (msg.msg_control) {
854 if (msg.msg_controllen < sizeof(struct cmsghdr) ||
855 msg.msg_controllen > MLEN) {
859 control = m_get(MB_WAIT, MT_CONTROL);
860 if (control == NULL) {
864 control->m_len = msg.msg_controllen;
865 error = copyin(msg.msg_control, mtod(control, caddr_t),
872 * Linux and BSD both support SCM_RIGHTS. If a linux binary
873 * wants anything else with an option level of SOL_SOCKET,
874 * we don't support it.
876 if (mtod(control, struct cmsghdr *)->cmsg_level ==
878 mtod(control, struct cmsghdr *)->cmsg_type !=
886 error = kern_sendmsg(linux_args.s, sa, &auio, control,
887 linux_args.flags, res);
892 iovec_free(&iov, aiov);
896 struct linux_recvmsg_args {
903 linux_recvmsg(struct linux_recvmsg_args *args, int *res)
905 struct linux_recvmsg_args linux_args;
906 struct thread *td = curthread;
909 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
910 struct mbuf *m, *control = NULL;
911 struct sockaddr *sa = NULL;
913 socklen_t *ufromlenp, *ucontrollenp;
914 int error, fromlen, controllen, len, flags, *uflagsp;
916 error = copyin(args, &linux_args, sizeof(linux_args));
920 error = copyin(linux_args.msg, &msg, sizeof(struct msghdr));
924 if (msg.msg_name && msg.msg_namelen < 0)
926 if (msg.msg_control && msg.msg_controllen < 0)
929 ufromlenp = (socklen_t *)((caddr_t)linux_args.msg +
930 offsetof(struct msghdr, msg_namelen));
931 ucontrollenp = (socklen_t *)((caddr_t)linux_args.msg +
932 offsetof(struct msghdr, msg_controllen));
933 uflagsp = (int *)((caddr_t)linux_args.msg +
934 offsetof(struct msghdr, msg_flags));
939 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
944 auio.uio_iovcnt = msg.msg_iovlen;
946 auio.uio_segflg = UIO_USERSPACE;
947 auio.uio_rw = UIO_READ;
950 flags = linux_to_bsd_msg_flags(linux_args.flags);
952 error = kern_recvmsg(linux_args.s, msg.msg_name ? &sa : NULL, &auio,
953 msg.msg_control ? &control : NULL, &flags, res);
956 * Copyout msg.msg_name and msg.msg_namelen.
958 if (error == 0 && msg.msg_name) {
959 fromlen = MIN(msg.msg_namelen, sa->sa_len);
960 error = linux_copyout_sockaddr(sa, msg.msg_name, fromlen);
962 error = copyout(&fromlen, ufromlenp,
967 * Copyout msg.msg_control and msg.msg_controllen.
969 if (error == 0 && msg.msg_control) {
971 * Linux and BSD both support SCM_RIGHTS. If a linux binary
972 * wants anything else with an option level of SOL_SOCKET,
973 * we don't support it.
975 if (mtod((struct mbuf *)msg.msg_control,
976 struct cmsghdr *)->cmsg_level == SOL_SOCKET &&
977 mtod((struct mbuf *)msg.msg_control,
978 struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
983 len = msg.msg_controllen;
985 ctlbuf = (caddr_t)msg.msg_control;
987 while (m && len > 0) {
990 if (len >= m->m_len) {
993 msg.msg_flags |= MSG_CTRUNC;
997 error = copyout(mtod(m, caddr_t), ctlbuf,
1006 controllen = ctlbuf - (caddr_t)msg.msg_control;
1007 error = copyout(&controllen, ucontrollenp,
1008 sizeof(*ucontrollenp));
1012 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
1017 iovec_free(&iov, aiov);
1023 struct linux_shutdown_args {
1029 linux_shutdown(struct linux_shutdown_args *args, int *res)
1031 struct linux_shutdown_args linux_args;
1034 error = copyin(args, &linux_args, sizeof(linux_args));
1038 error = kern_shutdown(linux_args.s, linux_args.how);
1043 struct linux_setsockopt_args {
1052 linux_setsockopt(struct linux_setsockopt_args *args, int *res)
1054 struct linux_setsockopt_args linux_args;
1055 struct thread *td = curthread;
1056 struct sockopt sopt;
1057 int error, name, level;
1059 error = copyin(args, &linux_args, sizeof(linux_args));
1063 level = linux_to_bsd_sockopt_level(linux_args.level);
1066 name = linux_to_bsd_so_sockopt(linux_args.optname);
1069 name = linux_to_bsd_ip_sockopt(linux_args.optname);
1072 /* Linux TCP option values match BSD's */
1073 name = linux_args.optname;
1082 sopt.sopt_dir = SOPT_SET;
1083 sopt.sopt_level = level;
1084 sopt.sopt_name = name;
1085 sopt.sopt_val = linux_args.optval;
1086 sopt.sopt_valsize = linux_args.optlen;
1089 error = kern_setsockopt(linux_args.s, &sopt);
1093 struct linux_getsockopt_args {
1102 linux_getsockopt(struct linux_getsockopt_args *args, int *res)
1104 struct linux_getsockopt_args linux_args;
1105 struct thread *td = curthread;
1106 struct sockopt sopt;
1107 int error, name, valsize, level;
1109 error = copyin(args, &linux_args, sizeof(linux_args));
1113 if (linux_args.optval) {
1114 error = copyin(linux_args.optlen, &valsize, sizeof(valsize));
1123 level = linux_to_bsd_sockopt_level(linux_args.level);
1126 name = linux_to_bsd_so_sockopt(linux_args.optname);
1129 name = linux_to_bsd_ip_sockopt(linux_args.optname);
1132 /* Linux TCP option values match BSD's */
1133 name = linux_args.optname;
1142 sopt.sopt_dir = SOPT_GET;
1143 sopt.sopt_level = level;
1144 sopt.sopt_name = name;
1145 sopt.sopt_val = linux_args.optval;
1146 sopt.sopt_valsize = valsize;
1149 error = kern_getsockopt(linux_args.s, &sopt);
1151 valsize = sopt.sopt_valsize;
1152 error = copyout(&valsize, linux_args.optlen, sizeof(valsize));
1158 linux_socketcall(struct linux_socketcall_args *args)
1160 void *arg = (void *)args->args;
1162 switch (args->what) {
1164 return (linux_socket(arg, &args->sysmsg_result));
1166 return (linux_bind(arg, &args->sysmsg_result));
1168 return (linux_connect(arg, &args->sysmsg_result));
1170 return (linux_listen(arg, &args->sysmsg_result));
1172 return (linux_accept(arg, &args->sysmsg_result));
1173 case LINUX_GETSOCKNAME:
1174 return (linux_getsockname(arg, &args->sysmsg_result));
1175 case LINUX_GETPEERNAME:
1176 return (linux_getpeername(arg, &args->sysmsg_result));
1177 case LINUX_SOCKETPAIR:
1178 return (linux_socketpair(arg, &args->sysmsg_result));
1180 return (linux_send(arg, &args->sysmsg_result));
1182 return (linux_recv(arg, &args->sysmsg_result));
1184 return (linux_sendto(arg, &args->sysmsg_result));
1185 case LINUX_RECVFROM:
1186 return (linux_recvfrom(arg, &args->sysmsg_result));
1187 case LINUX_SHUTDOWN:
1188 return (linux_shutdown(arg, &args->sysmsg_result));
1189 case LINUX_SETSOCKOPT:
1190 return (linux_setsockopt(arg, &args->sysmsg_result));
1191 case LINUX_GETSOCKOPT:
1192 return (linux_getsockopt(arg, &args->sysmsg_result));
1194 return (linux_sendmsg(arg, &args->sysmsg_result));
1196 return (linux_recvmsg(arg, &args->sysmsg_result));
1199 uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
1202 #endif /*!__alpha__*/