Module Name:    src
Committed By:   christos
Date:           Fri Feb  3 16:57:39 UTC 2017

Modified Files:
        src/sys/compat/linux/common: linux_socket.c linux_socket.h
            linux_socketcall.c linux_socketcall.h

Log Message:
add sendmmsg and recvmmsg


To generate a diff of this commit:
cvs rdiff -u -r1.136 -r1.137 src/sys/compat/linux/common/linux_socket.c
cvs rdiff -u -r1.22 -r1.23 src/sys/compat/linux/common/linux_socket.h
cvs rdiff -u -r1.46 -r1.47 src/sys/compat/linux/common/linux_socketcall.c
cvs rdiff -u -r1.18 -r1.19 src/sys/compat/linux/common/linux_socketcall.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/compat/linux/common/linux_socket.c
diff -u src/sys/compat/linux/common/linux_socket.c:1.136 src/sys/compat/linux/common/linux_socket.c:1.137
--- src/sys/compat/linux/common/linux_socket.c:1.136	Fri Feb  3 08:08:08 2017
+++ src/sys/compat/linux/common/linux_socket.c	Fri Feb  3 11:57:39 2017
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: linux_socket
 #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_get_sa(struct lwp *, in
 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 @@ linux_sys_sendto(struct lwp *l, const st
 }
 
 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 @@ linux_to_bsd_msghdr(struct linux_msghdr 
 }
 
 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 @@ linux_sys_accept4(struct lwp *l, const s
 
 	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), &lts, 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;
+}

Index: src/sys/compat/linux/common/linux_socket.h
diff -u src/sys/compat/linux/common/linux_socket.h:1.22 src/sys/compat/linux/common/linux_socket.h:1.23
--- src/sys/compat/linux/common/linux_socket.h:1.22	Mon Jan 27 14:19:15 2014
+++ src/sys/compat/linux/common/linux_socket.h	Fri Feb  3 11:57:39 2017
@@ -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 @@ struct linux_msghdr {
 	unsigned int	msg_flags;
 };
 
+struct linux_mmsghdr {
+	struct linux_msghdr msg_hdr;
+	unsigned int msg_len;
+};
+
 /*
  * Message flags (for sendmsg/recvmsg)
  */

Index: src/sys/compat/linux/common/linux_socketcall.c
diff -u src/sys/compat/linux/common/linux_socketcall.c:1.46 src/sys/compat/linux/common/linux_socketcall.c:1.47
--- src/sys/compat/linux/common/linux_socketcall.c:1.46	Fri Feb  3 08:08:08 2017
+++ src/sys/compat/linux/common/linux_socketcall.c	Fri Feb  3 11:57:39 2017
@@ -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 @@ linux_sys_socketcall(struct lwp *l, cons
 	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;

Index: src/sys/compat/linux/common/linux_socketcall.h
diff -u src/sys/compat/linux/common/linux_socketcall.h:1.18 src/sys/compat/linux/common/linux_socketcall.h:1.19
--- src/sys/compat/linux/common/linux_socketcall.h:1.18	Fri Feb  3 08:08:08 2017
+++ src/sys/compat/linux/common/linux_socketcall.h	Fri Feb  3 11:57:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_socketcall.h,v 1.18 2017/02/03 13:08:08 christos Exp $	*/
+/*	$NetBSD: linux_socketcall.h,v 1.19 2017/02/03 16:57:39 christos Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -95,7 +95,7 @@
 #define LINUX_SYS_RECVMMSG	19
 #define LINUX_SYS_SENDMMSG	20
 
-#define LINUX_MAX_SOCKETCALL	18	/* no send/recv mmsg yet */
+#define LINUX_MAX_SOCKETCALL	20
 
 
 /*
@@ -231,6 +231,21 @@ struct linux_sys_accept4_args {
 	syscallarg(int) flags;
 };
 
+struct linux_sys_recvmmsg_args {
+	syscallarg(int) s;
+	syscallarg(struct linux_mmsghdr *) msgvec;
+	syscallarg(unsigned int) vlen;
+	syscallarg(unsigned int) flags;
+	syscallarg(struct linux_timespec *) timeout;
+};
+
+struct linux_sys_sendmmsg_args {
+	syscallarg(int) s;
+	syscallarg(struct linux_mmsghdr *) msgvec;
+	syscallarg(unsigned int) vlen;
+	syscallarg(unsigned int) flags;
+};
+
 # ifdef _KERNEL
 __BEGIN_DECLS
 #define SYS_DEF(foo) int foo(struct lwp *, const struct foo##_args *, register_t *);
@@ -250,6 +265,8 @@ SYS_DEF(linux_sys_recv)
 SYS_DEF(linux_sys_send)
 SYS_DEF(linux_sys_accept)
 SYS_DEF(linux_sys_accept4)
+SYS_DEF(linux_sys_recvmmsg)
+SYS_DEF(linux_sys_sendmmsg)
 #undef SYS_DEF
 __END_DECLS
 # endif /* !_KERNEL */

Reply via email to