summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2016-06-27 22:40:20 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2016-06-29 17:35:51 +0000
commitc04d94225b0cde562f80654761b4c3b1111da969 (patch)
tree5153a75ad4ca2ac09ed4db7fa88afd486e737930 /usr/src
parentf877ab6aa38f6c8251e51e0d2a92c45b3b1b4f04 (diff)
downloadillumos-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.com1
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/lx_brand.c8
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/socket.c329
-rw-r--r--usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h5
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_syscall.c6
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_syscalls.h3
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_socket.c255
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));
}
/*