Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/compat/linux/common add sendmmsg and recvmmsg
details: https://anonhg.NetBSD.org/src/rev/1a9336b06c45
branches: trunk
changeset: 351150:1a9336b06c45
user: christos <christos%NetBSD.org@localhost>
date: Fri Feb 03 16:57:39 2017 +0000
description:
add sendmmsg and recvmmsg
diffstat:
sys/compat/linux/common/linux_socket.c | 200 ++++++++++++++++++++++++++++-
sys/compat/linux/common/linux_socket.h | 7 +-
sys/compat/linux/common/linux_socketcall.c | 10 +-
sys/compat/linux/common/linux_socketcall.h | 21 ++-
4 files changed, 227 insertions(+), 11 deletions(-)
diffs (truncated from 347 to 300 lines):
diff -r 0d3c18c39372 -r 1a9336b06c45 sys/compat/linux/common/linux_socket.c
--- a/sys/compat/linux/common/linux_socket.c Fri Feb 03 16:56:55 2017 +0000
+++ b/sys/compat/linux/common/linux_socket.c Fri Feb 03 16:57:39 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_socket.c,v 1.136 2017/02/03 13:08:08 christos Exp $ */
+/* $NetBSD: linux_socket.c,v 1.137 2017/02/03 16:57:39 christos Exp $ */
/*-
* Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.136 2017/02/03 13:08:08 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.137 2017/02/03 16:57:39 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -82,6 +82,7 @@
#include <compat/linux/common/linux_util.h>
#include <compat/linux/common/linux_signal.h>
#include <compat/linux/common/linux_ioctl.h>
+#include <compat/linux/common/linux_sched.h>
#include <compat/linux/common/linux_socket.h>
#include <compat/linux/common/linux_fcntl.h>
#if !defined(__alpha__) && !defined(__amd64__)
@@ -124,8 +125,8 @@
static int linux_sa_put(struct osockaddr *osa);
static int linux_to_bsd_msg_flags(int);
static int bsd_to_linux_msg_flags(int);
-static void linux_to_bsd_msghdr(struct linux_msghdr *, struct msghdr *);
-static void bsd_to_linux_msghdr(struct msghdr *, struct linux_msghdr *);
+static void linux_to_bsd_msghdr(const struct linux_msghdr *, struct msghdr *);
+static void bsd_to_linux_msghdr(const struct msghdr *, struct linux_msghdr *);
static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
AF_UNSPEC,
@@ -433,7 +434,7 @@
}
static void
-linux_to_bsd_msghdr(struct linux_msghdr *lmsg, struct msghdr *bmsg)
+linux_to_bsd_msghdr(const struct linux_msghdr *lmsg, struct msghdr *bmsg)
{
bmsg->msg_name = lmsg->msg_name;
bmsg->msg_namelen = lmsg->msg_namelen;
@@ -445,7 +446,7 @@
}
static void
-bsd_to_linux_msghdr(struct msghdr *bmsg, struct linux_msghdr *lmsg)
+bsd_to_linux_msghdr(const struct msghdr *bmsg, struct linux_msghdr *lmsg)
{
lmsg->msg_name = bmsg->msg_name;
lmsg->msg_namelen = bmsg->msg_namelen;
@@ -1742,3 +1743,190 @@
return 0;
}
+
+int
+linux_sys_sendmmsg(struct lwp *l, const struct linux_sys_sendmmsg_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(int) s;
+ syscallarg(struct linux_mmsghdr *) msgvec;
+ syscallarg(unsigned int) vlen;
+ syscallarg(unsigned int) flags;
+ } */
+ struct linux_mmsghdr lmsg;
+ struct mmsghdr bmsg;
+ struct socket *so;
+ file_t *fp;
+ struct msghdr *msg = &bmsg.msg_hdr;
+ int error, s;
+ unsigned int vlen, flags, dg;
+
+ if ((flags = linux_to_bsd_msg_flags(SCARG(uap, flags))) == -1)
+ return EINVAL;
+
+ flags = (flags & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
+
+ s = SCARG(uap, s);
+ if ((error = fd_getsock1(s, &so, &fp)) != 0)
+ return error;
+
+ vlen = SCARG(uap, vlen);
+ if (vlen > 1024)
+ vlen = 1024;
+
+ for (dg = 0; dg < vlen;) {
+ error = copyin(SCARG(uap, msgvec) + dg, &lmsg, sizeof(lmsg));
+ if (error)
+ break;
+ linux_to_bsd_msghdr(&lmsg.msg_hdr, &bmsg.msg_hdr);
+
+ msg->msg_flags = flags;
+
+ error = do_sys_sendmsg_so(l, s, so, fp, msg, flags,
+ &msg, sizeof(msg), retval);
+ if (error)
+ break;
+
+ ktrkuser("msghdr", msg, sizeof *msg);
+ lmsg.msg_len = *retval;
+ error = copyout(&lmsg, SCARG(uap, msgvec) + dg, sizeof(lmsg));
+ if (error)
+ break;
+ dg++;
+
+ }
+
+ *retval = dg;
+ if (error)
+ so->so_error = error;
+
+ fd_putfile(s);
+
+ /*
+ * If we succeeded at least once, return 0, hopefully so->so_error
+ * will catch it next time.
+ */
+ if (dg)
+ return 0;
+ return error;
+}
+
+int
+linux_sys_recvmmsg(struct lwp *l, const struct linux_sys_recvmmsg_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(int) s;
+ syscallarg(struct linux_mmsghdr *) msgvec;
+ syscallarg(unsigned int) vlen;
+ syscallarg(unsigned int) flags;
+ syscallarg(struct linux_timespec *) timeout;
+ } */
+ struct linux_mmsghdr lmsg;
+ struct mmsghdr bmsg;
+ struct socket *so;
+ struct msghdr *msg = &bmsg.msg_hdr;
+ int error, s;
+ struct mbuf *from, *control;
+ struct timespec ts, now;
+ struct linux_timespec lts;
+ unsigned int vlen, flags, dg;
+
+ if (SCARG(uap, timeout)) {
+ error = copyin(SCARG(uap, timeout), <s, sizeof(lts));
+ return error;
+ ts.tv_sec = lts.tv_sec;
+ ts.tv_nsec = lts.tv_nsec;
+ getnanotime(&now);
+ timespecadd(&now, &ts, &ts);
+ }
+
+ s = SCARG(uap, s);
+ if ((error = fd_getsock(s, &so)) != 0)
+ return error;
+
+ vlen = SCARG(uap, vlen);
+ if (vlen > 1024)
+ vlen = 1024;
+
+ from = NULL;
+ flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
+
+ for (dg = 0; dg < vlen;) {
+ error = copyin(SCARG(uap, msgvec) + dg, &lmsg, sizeof(lmsg));
+ if (error)
+ break;
+ linux_to_bsd_msghdr(&lmsg.msg_hdr, &bmsg.msg_hdr);
+ msg->msg_flags = flags & ~MSG_WAITFORONE;
+
+ if (from != NULL) {
+ m_free(from);
+ from = NULL;
+ }
+
+ error = do_sys_recvmsg_so(l, s, so, msg, NULL, 0, &from,
+ msg->msg_control != NULL ? &control : NULL, retval);
+ if (error) {
+ if (error == EAGAIN && dg > 0)
+ error = 0;
+ break;
+ }
+
+ if (msg->msg_control != NULL)
+ error = linux_copyout_msg_control(l, msg, control);
+ if (error)
+ break;
+
+ if (from != NULL) {
+ mtod(from, struct osockaddr *)->sa_family =
+ bsd_to_linux_domain(mtod(from,
+ struct sockaddr *)->sa_family);
+ error = copyout_sockname(msg->msg_name,
+ &msg->msg_namelen, 0, from);
+ if (error)
+ break;
+ }
+
+
+ lmsg.msg_len = *retval;
+ ktrkuser("msghdr", msg, sizeof(*msg));
+ bsd_to_linux_msghdr(msg, &lmsg.msg_hdr);
+ error = copyout(&lmsg, SCARG(uap, msgvec) + dg, sizeof(lmsg));
+ if (error)
+ break;
+
+ dg++;
+ if (msg->msg_flags & MSG_OOB)
+ break;
+
+ if (SCARG(uap, timeout)) {
+ getnanotime(&now);
+ timespecsub(&now, &ts, &now);
+ if (now.tv_sec > 0)
+ break;
+ }
+
+ if (flags & MSG_WAITFORONE)
+ flags |= MSG_DONTWAIT;
+
+ }
+
+ if (from != NULL)
+ m_free(from);
+
+ *retval = dg;
+ if (error)
+ so->so_error = error;
+
+ fd_putfile(s);
+
+ /*
+ * If we succeeded at least once, return 0, hopefully so->so_error
+ * will catch it next time.
+ */
+ if (dg)
+ return 0;
+
+ return error;
+}
diff -r 0d3c18c39372 -r 1a9336b06c45 sys/compat/linux/common/linux_socket.h
--- a/sys/compat/linux/common/linux_socket.h Fri Feb 03 16:56:55 2017 +0000
+++ b/sys/compat/linux/common/linux_socket.h Fri Feb 03 16:57:39 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_socket.h,v 1.22 2014/01/27 19:19:15 njoly Exp $ */
+/* $NetBSD: linux_socket.h,v 1.23 2017/02/03 16:57:39 christos Exp $ */
/*-
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -140,6 +140,11 @@
unsigned int msg_flags;
};
+struct linux_mmsghdr {
+ struct linux_msghdr msg_hdr;
+ unsigned int msg_len;
+};
+
/*
* Message flags (for sendmsg/recvmsg)
*/
diff -r 0d3c18c39372 -r 1a9336b06c45 sys/compat/linux/common/linux_socketcall.c
--- a/sys/compat/linux/common/linux_socketcall.c Fri Feb 03 16:56:55 2017 +0000
+++ b/sys/compat/linux/common/linux_socketcall.c Fri Feb 03 16:57:39 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_socketcall.c,v 1.46 2017/02/03 13:08:08 christos Exp $ */
+/* $NetBSD: linux_socketcall.c,v 1.47 2017/02/03 16:57:39 christos Exp $ */
/*-
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_socketcall.c,v 1.46 2017/02/03 13:08:08 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_socketcall.c,v 1.47 2017/02/03 16:57:39 christos Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -219,6 +219,12 @@
case LINUX_SYS_ACCEPT4:
error = linux_sys_accept4(l, (void *)&lda, retval);
break;
+ case LINUX_SYS_RECVMMSG:
+ error = linux_sys_recvmmsg(l, (void *)&lda, retval);
+ break;
+ case LINUX_SYS_SENDMMSG:
+ error = linux_sys_sendmmsg(l, (void *)&lda, retval);
+ break;
default:
error = ENOSYS;
break;
diff -r 0d3c18c39372 -r 1a9336b06c45 sys/compat/linux/common/linux_socketcall.h
--- a/sys/compat/linux/common/linux_socketcall.h Fri Feb 03 16:56:55 2017 +0000
Home |
Main Index |
Thread Index |
Old Index