diff options
| author | Patrick Mooney <pmooney@pfmooney.com> | 2016-06-27 22:40:20 +0000 |
|---|---|---|
| committer | Patrick Mooney <pmooney@pfmooney.com> | 2016-06-29 17:35:51 +0000 |
| commit | c04d94225b0cde562f80654761b4c3b1111da969 (patch) | |
| tree | 5153a75ad4ca2ac09ed4db7fa88afd486e737930 /usr/src | |
| parent | f877ab6aa38f6c8251e51e0d2a92c45b3b1b4f04 (diff) | |
| download | illumos-joyent-c04d94225b0cde562f80654761b4c3b1111da969.tar.gz | |
OS-5491 lxbrand convert last socket syscalls to IKE
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/Makefile.com | 1 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/lx_brand.c | 8 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/socket.c | 329 | ||||
| -rw-r--r-- | usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h | 5 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_syscall.c | 6 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_syscalls.h | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_socket.c | 255 |
7 files changed, 235 insertions, 372 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/Makefile.com b/usr/src/lib/brand/lx/lx_brand/Makefile.com index 13e7636333..68df72849b 100644 --- a/usr/src/lib/brand/lx/lx_brand/Makefile.com +++ b/usr/src/lib/brand/lx/lx_brand/Makefile.com @@ -50,7 +50,6 @@ COBJS = aio.o \ sched.o \ sendfile.o \ signal.o \ - socket.o \ stack.o \ statfs.o \ sysctl.o \ diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c index 8b021d6b1f..5f71e6286e 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c +++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c @@ -1059,12 +1059,12 @@ static lx_syscall_handler_t lx_handlers[] = { NULL, /* 45: recvfrom */ NULL, /* 46: sendmsg */ NULL, /* 47: recvmsg */ - lx_shutdown, /* 48: shutdown */ + NULL, /* 48: shutdown */ NULL, /* 49: bind */ - lx_listen, /* 50: listen */ + NULL, /* 50: listen */ NULL, /* 51: getsockname */ NULL, /* 52: getpeername */ - lx_socketpair, /* 53: socketpair */ + NULL, /* 53: socketpair */ NULL, /* 54: setsockopt */ NULL, /* 55: getsockopt */ lx_clone, /* 56: clone */ @@ -1444,7 +1444,7 @@ static lx_syscall_handler_t lx_handlers[] = { lx_statfs, /* 99: statfs */ lx_fstatfs, /* 100: fstatfs */ NULL, /* 101: ioperm */ - lx_socketcall, /* 102: socketcall */ + NULL, /* 102: socketcall */ lx_syslog, /* 103: syslog */ lx_setitimer, /* 104: setitimer */ lx_getitimer, /* 105: getitimer */ diff --git a/usr/src/lib/brand/lx/lx_brand/common/socket.c b/usr/src/lib/brand/lx/lx_brand/common/socket.c deleted file mode 100644 index ad035dfce8..0000000000 --- a/usr/src/lib/brand/lx/lx_brand/common/socket.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright 2016 Joyent, Inc. - */ - -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <libintl.h> -#include <strings.h> -#include <alloca.h> -#include <ucred.h> -#include <limits.h> - -#include <sys/param.h> -#include <sys/brand.h> -#include <sys/syscall.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/un.h> -#include <netinet/tcp.h> -#include <netinet/igmp.h> -#include <netinet/icmp6.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/sysmacros.h> -#include <sys/lx_debug.h> -#include <sys/lx_syscall.h> -#include <sys/lx_socket.h> -#include <sys/lx_brand.h> -#include <sys/lx_misc.h> -#include <netpacket/packet.h> - -#ifdef __i386 - -static int lx_listen32(ulong_t *); -static int lx_socketpair32(ulong_t *); -static int lx_shutdown32(ulong_t *); -static int lx_recvmmsg32(ulong_t *); -static int lx_sendmmsg32(ulong_t *); - -typedef int (*sockfn_t)(ulong_t *); - -static struct { - sockfn_t s_fn; /* Function implementing the subcommand */ - int s_nargs; /* Number of arguments the function takes */ -} sockfns[] = { - NULL, 3, - NULL, 3, - NULL, 3, - lx_listen32, 2, - NULL, 3, - NULL, 3, - NULL, 3, - lx_socketpair32, 4, - NULL, 4, - NULL, 4, - NULL, 6, - NULL, 6, - lx_shutdown32, 2, - NULL, 5, - NULL, 5, - NULL, 3, - NULL, 3, - NULL, 4, - lx_recvmmsg32, 5, - lx_sendmmsg32, 4 -}; -#endif /* __i386 */ - -/* - * What follows are a series of tables we use to translate Linux constants - * into equivalent Illumos constants and back again. I wish this were - * cleaner, more programmatic, and generally nicer. Sadly, life is messy, - * and Unix networking even more so. - */ -static const int ltos_family[LX_AF_MAX + 1] = { - AF_UNSPEC, AF_UNIX, AF_INET, AF_NOTSUPPORTED, AF_NOTSUPPORTED, - AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, - AF_NOTSUPPORTED, AF_INET6, AF_NOTSUPPORTED, AF_NOTSUPPORTED, - AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_LX_NETLINK, - AF_PACKET, AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, - AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, - AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, - AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, AF_NOTSUPPORTED, - AF_NOTSUPPORTED -}; - -#define LTOS_FAMILY(d) ((d) <= LX_AF_MAX ? ltos_family[(d)] : AF_INVAL) - -static const int ltos_socktype[LX_SOCK_PACKET + 1] = { - SOCK_NOTSUPPORTED, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, - SOCK_RDM, SOCK_SEQPACKET, SOCK_NOTSUPPORTED, SOCK_NOTSUPPORTED, - SOCK_NOTSUPPORTED, SOCK_NOTSUPPORTED, SOCK_NOTSUPPORTED -}; - -#define LTOS_SOCKTYPE(t) \ - ((t) <= LX_SOCK_PACKET ? ltos_socktype[(t)] : SOCK_INVAL) - -typedef struct { - sa_family_t nl_family; - unsigned short nl_pad; - uint32_t nl_pid; - uint32_t nl_groups; -} lx_sockaddr_nl_t; - -typedef struct { - sa_family_t sin6_family; - in_port_t sin6_port; - uint32_t sin6_flowinfo; - struct in6_addr sin6_addr; - uint32_t sin6_scope_id; /* Depends on scope of sin6_addr */ - /* one 32-bit field shorter than illumos */ -} lx_sockaddr_in6_t; - -static int -convert_pkt_proto(int protocol) -{ - switch (ntohs(protocol)) { - case LX_ETH_P_802_2: - return (ETH_P_802_2); - case LX_ETH_P_IP: - return (ETH_P_IP); - case LX_ETH_P_ARP: - return (ETH_P_ARP); - case LX_ETH_P_IPV6: - return (ETH_P_IPV6); - case LX_ETH_P_ALL: - case LX_ETH_P_802_3: - return (ETH_P_ALL); - default: - return (-1); - } -} - -static int -convert_sock_args(int in_dom, int in_type, int in_protocol, int *out_dom, - int *out_type, int *out_options, int *out_protocol) -{ - int domain, type, options; - - if (in_dom < 0 || in_type < 0 || in_protocol < 0) - return (-EINVAL); - - domain = LTOS_FAMILY(in_dom); - if (domain == AF_NOTSUPPORTED || domain == AF_UNSPEC) - return (-EAFNOSUPPORT); - if (domain == AF_INVAL) - return (-EINVAL); - - type = LTOS_SOCKTYPE(in_type & LX_SOCK_TYPE_MASK); - if (type == SOCK_NOTSUPPORTED) - return (-ESOCKTNOSUPPORT); - if (type == SOCK_INVAL) - return (-EINVAL); - - /* - * Linux does not allow the app to specify IP Protocol for raw - * sockets. Illumos does, so bail out here. - */ - if (domain == AF_INET && type == SOCK_RAW && in_protocol == IPPROTO_IP) - return (-ESOCKTNOSUPPORT); - - options = 0; - if (in_type & LX_SOCK_NONBLOCK) - options |= SOCK_NONBLOCK; - if (in_type & LX_SOCK_CLOEXEC) - options |= SOCK_CLOEXEC; - - /* - * The protocol definitions for PF_PACKET differ between Linux and - * illumos. - */ - if (domain == PF_PACKET && - (in_protocol = convert_pkt_proto(in_protocol)) < 0) - return (EINVAL); - - *out_dom = domain; - *out_type = type; - *out_options = options; - *out_protocol = in_protocol; - return (0); -} - -long -lx_listen(int sockfd, int backlog) -{ - int r; - - lx_debug("\tlisten(%d, %d)", sockfd, backlog); - r = listen(sockfd, backlog); - - return ((r < 0) ? -errno : r); -} - -long -lx_socketpair(int domain, int type, int protocol, int *sv) -{ - int options; - int fds[2]; - int r; - - r = convert_sock_args(domain, type, protocol, &domain, &type, &options, - &protocol); - if (r != 0) - return (r); - - lx_debug("\tsocketpair(%d, %d, %d, 0x%p)", domain, type, protocol, sv); - - r = socketpair(domain, type | options, protocol, fds); - - if (r == 0) { - if (uucopy(fds, sv, sizeof (fds)) != 0) { - r = errno; - (void) close(fds[0]); - (void) close(fds[1]); - return (-r); - } - return (0); - } - - if (errno == EPROTONOSUPPORT) - return (-ESOCKTNOSUPPORT); - - return (-errno); -} - -long -lx_shutdown(int sockfd, int how) -{ - int r; - - lx_debug("\tshutdown(%d, %d)", sockfd, how); - r = shutdown(sockfd, how); - - return ((r < 0) ? -errno : r); -} - -#ifdef __i386 - -static int -lx_listen32(ulong_t *args) -{ - return (lx_listen((int)args[0], (int)args[1])); -} - -static int -lx_socketpair32(ulong_t *args) -{ - return (lx_socketpair((int)args[0], (int)args[1], (int)args[2], - (int *)args[3])); -} - -static int -lx_shutdown32(ulong_t *args) -{ - return (lx_shutdown((int)args[0], (int)args[1])); -} - -/* ARGSUSED */ -static int -lx_recvmmsg32(ulong_t *args) -{ - lx_unsupported("Unsupported socketcall: recvmmsg\n."); - return (-EINVAL); -} - -/* ARGSUSED */ -static int -lx_sendmmsg32(ulong_t *args) -{ - lx_unsupported("Unsupported socketcall: sendmmsg\n."); - return (-EINVAL); -} - -long -lx_socketcall(uintptr_t p1, uintptr_t p2) -{ - int subcmd = (int)p1 - 1; /* subcommands start at 1 - not 0 */ - ulong_t args[6]; - int r; - - if (subcmd < 0 || subcmd >= LX_SENDMMSG) - return (-EINVAL); - - /* Bail out if we are trying to call an IKE function */ - if (sockfns[subcmd].s_fn == NULL) { - lx_err_fatal("lx_socketcall: deprecated subcmd: %d", subcmd); - } - - /* - * Copy the arguments to the subcommand in from the app's address - * space, returning EFAULT if we get a bogus pointer. - */ - if (uucopy((void *)p2, args, - sockfns[subcmd].s_nargs * sizeof (ulong_t))) - return (-errno); - - r = (sockfns[subcmd].s_fn)(args); - - return (r); -} - -#endif /* __i386 */ diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h index 6e43300e35..5b46311a3e 100644 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h @@ -72,11 +72,6 @@ extern long lx_vhangup(void); extern long lx_fadvise64(uintptr_t, off64_t, uintptr_t, uintptr_t); extern long lx_fadvise64_64(uintptr_t, off64_t, off64_t, uintptr_t); -extern long lx_socketcall(uintptr_t, uintptr_t); -extern long lx_listen(int, int); -extern long lx_shutdown(int, int); -extern long lx_socketpair(int, int, int, int *); - extern long lx_settimeofday(uintptr_t, uintptr_t); extern long lx_getrusage(uintptr_t, uintptr_t); extern long lx_mknod(uintptr_t, uintptr_t, uintptr_t); diff --git a/usr/src/uts/common/brand/lx/os/lx_syscall.c b/usr/src/uts/common/brand/lx/os/lx_syscall.c index 421de407d1..4371cd801d 100644 --- a/usr/src/uts/common/brand/lx/os/lx_syscall.c +++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c @@ -1033,12 +1033,12 @@ lx_sysent_t lx_sysent64[] = { {"recvfrom", lx_recvfrom, 0, 6}, /* 45 */ {"sendmsg", lx_sendmsg, 0, 3}, /* 46 */ {"recvmsg", lx_recvmsg, 0, 3}, /* 47 */ - {"shutdown", NULL, 0, 2}, /* 48 */ + {"shutdown", lx_shutdown, 0, 2}, /* 48 */ {"bind", lx_bind, 0, 3}, /* 49 */ - {"listen", NULL, 0, 2}, /* 50 */ + {"listen", lx_listen, 0, 2}, /* 50 */ {"getsockname", lx_getsockname, 0, 3}, /* 51 */ {"getpeername", lx_getpeername, 0, 3}, /* 52 */ - {"socketpair", NULL, 0, 4}, /* 53 */ + {"socketpair", lx_socketpair, 0, 4}, /* 53 */ {"setsockopt", lx_setsockopt, 0, 5}, /* 54 */ {"getsockopt", lx_getsockopt, 0, 5}, /* 55 */ {"clone", NULL, 0, 5}, /* 56 */ diff --git a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h index 64084b77f1..ff9674b2c5 100644 --- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h +++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h @@ -98,6 +98,7 @@ extern long lx_lchown16(); extern long lx_lgetxattr(); extern long lx_link(); extern long lx_linkat(); +extern long lx_listen(); extern long lx_llistxattr(); extern long lx_lremovexattr(); extern long lx_lsetxattr(); @@ -153,8 +154,10 @@ extern long lx_setresuid16(); extern long lx_setrlimit(); extern long lx_setxattr(); extern long lx_setsockopt(); +extern long lx_shutdown(); extern long lx_socket(); extern long lx_socketcall(); +extern long lx_socketpair(); extern long lx_stat32(); extern long lx_stat64(); extern long lx_sync_file_range(); diff --git a/usr/src/uts/common/brand/lx/syscall/lx_socket.c b/usr/src/uts/common/brand/lx/syscall/lx_socket.c index 2a049adb46..ae9eb1a7d8 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_socket.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_socket.c @@ -60,6 +60,9 @@ #include <sys/lx_types.h> #include <sys/lx_impl.h> +/* From uts/common/fs/sockfs/socksyscalls.c */ +extern int listen(int, int, int); +extern int shutdown(int, int, int); typedef struct lx_ucred { pid_t lxu_pid; @@ -1315,36 +1318,36 @@ lx_convert_sock_args(int in_dom, int in_type, int in_proto, int *out_dom, return (0); } -long -lx_socket(int domain, int type, int protocol) + +static int +lx_socket_create(int domain, int type, int protocol, int options, file_t **fpp, + int *fdp) { - int fd, error, options; sonode_t *so; vnode_t *vp; - struct file *fp; - - if ((error = lx_convert_sock_args(domain, type, protocol, &domain, - &type, &options, &protocol)) != 0) { - return (set_errno(error)); - } + file_t *fp; + int err, fd; /* logic cloned from so_socket */ so = socket_create(domain, type, protocol, NULL, NULL, SOCKET_SLEEP, - SOV_DEFAULT, CRED(), &error); + SOV_DEFAULT, CRED(), &err); if (so == NULL) { - if (error == EPROTOTYPE || error == EPROTONOSUPPORT) { - error = ESOCKTNOSUPPORT; + switch (err) { + case EPROTOTYPE: + case EPROTONOSUPPORT: + return (ESOCKTNOSUPPORT); + default: + return (err); } - return (set_errno(error)); } /* Allocate a file descriptor for the socket */ vp = SOTOV(so); - if ((error = falloc(vp, FWRITE|FREAD, &fp, &fd)) != 0) { + if ((err = falloc(vp, FWRITE|FREAD, &fp, &fd)) != 0) { (void) socket_close(so, 0, CRED()); socket_destroy(so); - return (set_errno(error)); + return (err); } /* @@ -1360,6 +1363,41 @@ lx_socket(int domain, int type, int protocol) fp->f_flag |= FNONBLOCK; } mutex_exit(&fp->f_tlock); + *fpp = fp; + *fdp = fd; + return (0); +} + +static void +lx_socket_destroy(file_t *fp, int fd) +{ + sonode_t *so = VTOSO(fp->f_vnode); + + setf(fd, NULL); + + mutex_enter(&fp->f_tlock); + unfalloc(fp); + + (void) socket_close(so, 0, CRED()); + socket_destroy(so); +} + +long +lx_socket(int domain, int type, int protocol) +{ + int error, options, fd = -1; + file_t *fp = NULL; + + if ((error = lx_convert_sock_args(domain, type, protocol, &domain, + &type, &options, &protocol)) != 0) { + return (set_errno(error)); + } + + error = lx_socket_create(domain, type, protocol, options, &fp, &fd); + if (error != 0) { + return (set_errno(error)); + } + setf(fd, fp); if ((options & SOCK_CLOEXEC) != 0) { f_setfd(fd, FD_CLOEXEC); @@ -3657,6 +3695,172 @@ lx_accept4(int sockfd, void *np, int *nlp, int flags) (socklen_t *)nlp, flags)); } +long +lx_listen(int sockfd, int backlog) +{ + return (listen(sockfd, backlog, 0)); +} + +long +lx_shutdown(int sockfd, int how) +{ + return (shutdown(sockfd, how, 0)); +} + +/* + * Connect two sockets together for a socketpair. This is derived from + * so_socketpair, but forgoes the task of dealing with file descriptors. + */ +static int +lx_socketpair_connect(file_t *fp1, file_t *fp2) +{ + sonode_t *so1, *so2; + sotpi_info_t *sti1, *sti2; + struct sockaddr_ux name; + int error; + + so1 = VTOSO(fp1->f_vnode); + so2 = VTOSO(fp2->f_vnode); + sti1 = SOTOTPI(so1); + sti2 = SOTOTPI(so2); + + VERIFY(so1->so_ops == &sotpi_sonodeops && + so2->so_ops == &sotpi_sonodeops); + + if (so1->so_type == SOCK_DGRAM) { + /* + * Bind both sockets and connect them with each other. + */ + error = socket_bind(so1, NULL, 0, _SOBIND_UNSPEC, CRED()); + if (error) { + return (error); + } + error = socket_bind(so2, NULL, 0, _SOBIND_UNSPEC, CRED()); + if (error) { + return (error); + } + name.sou_family = AF_UNIX; + name.sou_addr = sti2->sti_ux_laddr; + error = socket_connect(so1, (struct sockaddr *)&name, + (socklen_t)sizeof (name), 0, _SOCONNECT_NOXLATE, CRED()); + if (error) { + return (error); + } + name.sou_addr = sti1->sti_ux_laddr; + error = socket_connect(so2, (struct sockaddr *)&name, + (socklen_t)sizeof (name), 0, _SOCONNECT_NOXLATE, CRED()); + return (error); + } else { + sonode_t *nso; + + /* + * Bind both sockets, with 'so1' being a listener. Connect + * 'so2' to 'so1', doing so as nonblocking to avoid waiting for + * soaccept to complete. Accept the connection on 'so1', + * replacing the socket/vnode in 'fp1' with the new connection. + * + * We could simply call socket_listen() here (which would do the + * binding automatically) if the code didn't rely on passing + * _SOBIND_NOXLATE to the TPI implementation of socket_bind(). + */ + error = socket_bind(so1, NULL, 0, _SOBIND_UNSPEC| + _SOBIND_NOXLATE|_SOBIND_LISTEN|_SOBIND_SOCKETPAIR, CRED()); + if (error) { + return (error); + } + error = socket_bind(so2, NULL, 0, _SOBIND_UNSPEC, CRED()); + if (error) { + return (error); + } + + name.sou_family = AF_UNIX; + name.sou_addr = sti1->sti_ux_laddr; + error = socket_connect(so2, + (struct sockaddr *)&name, + (socklen_t)sizeof (name), + FNONBLOCK, _SOCONNECT_NOXLATE, CRED()); + if (error != 0 && error != EINPROGRESS) { + return (error); + } + + error = socket_accept(so1, 0, CRED(), &nso); + if (error) { + return (error); + } + + /* wait for so2 being SS_CONNECTED */ + mutex_enter(&so2->so_lock); + error = sowaitconnected(so2, 0, 0); + mutex_exit(&so2->so_lock); + if (error != 0) { + (void) socket_close(nso, 0, CRED()); + socket_destroy(nso); + return (error); + } + + (void) socket_close(so1, 0, CRED()); + socket_destroy(so1); + fp1->f_vnode = SOTOV(nso); + } + return (0); +} + +long +lx_socketpair(int domain, int type, int protocol, int *sv) +{ + int err, options, fds[2]; + file_t *fps[2]; + + if ((err = lx_convert_sock_args(domain, type, protocol, &domain, &type, + &options, &protocol)) != 0) { + return (set_errno(err)); + } + + if ((err = lx_socket_create(domain, type, protocol, options, &fps[0], + &fds[0])) != 0) { + err = (err == EPROTONOSUPPORT) ? ESOCKTNOSUPPORT : err; + return (set_errno(err)); + } + + /* + * While it seems silly to check the family after socket creation, this + * is done to appease LTP when it tries some outlandish combinations of + * domain/type/protocol. The socket_create function is relied upon to + * emit the expected errors. + */ + if (VTOSO(fps[0]->f_vnode)->so_family != AF_UNIX) { + lx_socket_destroy(fps[0], fds[0]); + return (set_errno(EOPNOTSUPP)); + } + + if ((err = lx_socket_create(domain, type, protocol, options, &fps[1], + &fds[1])) != 0) { + lx_socket_destroy(fps[0], fds[0]); + return (set_errno(err)); + } + + err = lx_socketpair_connect(fps[0], fps[1]); + if (err != 0) { + lx_socket_destroy(fps[0], fds[0]); + lx_socket_destroy(fps[1], fds[1]); + return (set_errno(err)); + } + + setf(fds[0], fps[0]); + setf(fds[1], fps[1]); + if ((options & SOCK_CLOEXEC) != 0) { + f_setfd(fds[0], FD_CLOEXEC); + f_setfd(fds[1], FD_CLOEXEC); + } + if (copyout(fds, sv, sizeof (fds)) != 0) { + (void) closeandsetf(fds[0], NULL); + (void) closeandsetf(fds[1], NULL); + return (set_errno(EFAULT)); + } + return (0); +} + + #if defined(_SYSCALL32_IMPL) #define LX_SYS_SOCKETCALL 102 @@ -3671,16 +3875,16 @@ static struct { lx_socket, 3, /* socket */ lx_bind, 3, /* bind */ lx_connect, 3, /* connect */ - NULL, 2, /* listen */ + lx_listen, 2, /* listen */ lx_accept, 3, /* accept */ lx_getsockname, 3, /* getsockname */ lx_getpeername, 3, /* getpeername */ - NULL, 4, /* socketpair */ + lx_socketpair, 4, /* socketpair */ lx_send, 4, /* send */ lx_recv, 4, /* recv */ lx_sendto, 6, /* sendto */ lx_recvfrom, 6, /* recvfrom */ - NULL, 2, /* shutdown */ + lx_shutdown, 2, /* shutdown */ lx_setsockopt, 5, /* setsockopt */ lx_getsockopt, 5, /* getsockopt */ lx_sendmsg, 3, /* sendmsg */ @@ -3695,22 +3899,13 @@ lx_socketcall(long p1, uint32_t *p2) { int subcmd, i; unsigned long args[6] = { 0, 0, 0, 0, 0, 0 }; - lx_lwp_data_t *lwpd = ttolxlwp(curthread); /* incoming subcmds are 1-indexed */ subcmd = (int)p1 - 1; - if (subcmd < 0 || subcmd >= LX_SOCKETCALL_MAX) { - return (-EINVAL); - } - - /* Vector back out to userland emulation if we lack IKE */ - if (lx_socketcall_fns[subcmd].s_fn == NULL) { - uintptr_t uargs[2] = {p1, (uintptr_t)p2}; - /* The userspace emulation will handle the syscall return */ - lwpd->br_eosys = JUSTRETURN; - lx_emulate_user32(ttolwp(curthread), LX_SYS_SOCKETCALL, uargs); - return (0); + if (subcmd < 0 || subcmd >= LX_SOCKETCALL_MAX || + lx_socketcall_fns[subcmd].s_fn == NULL) { + return (set_errno(EINVAL)); } /* |
