Module Name:    src
Committed By:   christos
Date:           Thu May 10 02:36:08 UTC 2018

Modified Files:
        src/sys/compat/netbsd32: netbsd32.h netbsd32_compat_20.c
            netbsd32_conv.h netbsd32_socket.c syscalls.master

Log Message:
add {send,recv}mmsg


To generate a diff of this commit:
cvs rdiff -u -r1.117 -r1.118 src/sys/compat/netbsd32/netbsd32.h
cvs rdiff -u -r1.36 -r1.37 src/sys/compat/netbsd32/netbsd32_compat_20.c
cvs rdiff -u -r1.34 -r1.35 src/sys/compat/netbsd32/netbsd32_conv.h
cvs rdiff -u -r1.45 -r1.46 src/sys/compat/netbsd32/netbsd32_socket.c
cvs rdiff -u -r1.120 -r1.121 src/sys/compat/netbsd32/syscalls.master

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/netbsd32/netbsd32.h
diff -u src/sys/compat/netbsd32/netbsd32.h:1.117 src/sys/compat/netbsd32/netbsd32.h:1.118
--- src/sys/compat/netbsd32/netbsd32.h:1.117	Sat Apr 14 00:04:39 2018
+++ src/sys/compat/netbsd32/netbsd32.h	Wed May  9 22:36:07 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32.h,v 1.117 2018/04/14 04:04:39 mrg Exp $	*/
+/*	$NetBSD: netbsd32.h,v 1.118 2018/05/10 02:36:07 christos Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001, 2008, 2015 Matthew R. Green
@@ -715,6 +715,12 @@ struct netbsd32_omsghdr {
 	int		 msg_accrightslen;
 };
 
+typedef netbsd32_pointer_t netbsd32_mmsghdrp_t;
+struct netbsd32_mmsghdr {
+	struct netbsd32_msghdr msg_hdr;
+	unsigned int msg_len;
+};
+
 /* from <sys/stat.h> */
 typedef netbsd32_pointer_t netbsd32_stat12p_t;
 struct netbsd32_stat12 {		/* NetBSD-1.2 stat struct */

Index: src/sys/compat/netbsd32/netbsd32_compat_20.c
diff -u src/sys/compat/netbsd32/netbsd32_compat_20.c:1.36 src/sys/compat/netbsd32/netbsd32_compat_20.c:1.37
--- src/sys/compat/netbsd32/netbsd32_compat_20.c:1.36	Thu Apr 13 05:46:59 2017
+++ src/sys/compat/netbsd32/netbsd32_compat_20.c	Wed May  9 22:36:07 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_compat_20.c,v 1.36 2017/04/13 09:46:59 hannken Exp $	*/
+/*	$NetBSD: netbsd32_compat_20.c,v 1.37 2018/05/10 02:36:07 christos Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Matthew R. Green
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_20.c,v 1.36 2017/04/13 09:46:59 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_20.c,v 1.37 2018/05/10 02:36:07 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_com
 #include <sys/time.h>
 #include <sys/ktrace.h>
 #include <sys/vnode.h>
+#include <sys/socket.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
 #include <sys/namei.h>

Index: src/sys/compat/netbsd32/netbsd32_conv.h
diff -u src/sys/compat/netbsd32/netbsd32_conv.h:1.34 src/sys/compat/netbsd32/netbsd32_conv.h:1.35
--- src/sys/compat/netbsd32/netbsd32_conv.h:1.34	Thu Apr 19 17:50:08 2018
+++ src/sys/compat/netbsd32/netbsd32_conv.h	Wed May  9 22:36:07 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_conv.h,v 1.34 2018/04/19 21:50:08 christos Exp $	*/
+/*	$NetBSD: netbsd32_conv.h,v 1.35 2018/05/10 02:36:07 christos Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Matthew R. Green
@@ -289,6 +289,22 @@ netbsd32_from_msghdr(struct netbsd32_msg
 }
 
 static __inline void
+netbsd32_to_mmsghdr(const struct netbsd32_mmsghdr *mmsg32,
+    struct mmsghdr *mmsg)
+{
+    netbsd32_to_msghdr(&mmsg32->msg_hdr, &mmsg->msg_hdr);
+    mmsg->msg_len = mmsg32->msg_len;
+}
+
+static __inline void
+netbsd32_from_mmsghdr(struct netbsd32_mmsghdr *mmsg32,
+    const struct mmsghdr *mmsg)
+{
+    netbsd32_from_msghdr(&mmsg32->msg_hdr, &mmsg->msg_hdr);
+    mmsg32->msg_len = mmsg->msg_len;
+}
+
+static __inline void
 netbsd32_from_statvfs(const struct statvfs *sbp, struct netbsd32_statvfs *sb32p)
 {
 	sb32p->f_flag = sbp->f_flag;

Index: src/sys/compat/netbsd32/netbsd32_socket.c
diff -u src/sys/compat/netbsd32/netbsd32_socket.c:1.45 src/sys/compat/netbsd32/netbsd32_socket.c:1.46
--- src/sys/compat/netbsd32/netbsd32_socket.c:1.45	Thu May  3 17:43:33 2018
+++ src/sys/compat/netbsd32/netbsd32_socket.c	Wed May  9 22:36:07 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_socket.c,v 1.45 2018/05/03 21:43:33 christos Exp $	*/
+/*	$NetBSD: netbsd32_socket.c,v 1.46 2018/05/10 02:36:07 christos Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Matthew R. Green
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.45 2018/05/03 21:43:33 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.46 2018/05/10 02:36:07 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -159,6 +159,62 @@ copyout32_msg_control(struct lwp *l, str
 	return error;
 }
 
+static int
+msg_recv_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32,
+    struct msghdr *msg, struct iovec *aiov)
+{
+	int error;
+	size_t iovsz;
+	struct iovec *iov = aiov;
+
+	iovsz = msg32->msg_iovlen * sizeof(struct iovec);
+	if (msg32->msg_iovlen > UIO_SMALLIOV) {
+		if (msg32->msg_iovlen > IOV_MAX)
+			return EMSGSIZE;
+		iov = kmem_alloc(iovsz, KM_SLEEP);
+	}
+
+	error = netbsd32_to_iovecin(NETBSD32PTR64(msg32->msg_iov), iov,
+	    msg32->msg_iovlen);
+	if (error)
+		goto out;
+
+	netbsd32_to_msghdr(msg32, msg);
+	msg->msg_iov = iov;
+out:
+	if (iov != aiov)
+		kmem_free(iov, iovsz);
+	return error;
+}
+
+static int
+msg_recv_copyout(struct lwp *l, struct netbsd32_msghdr *msg32, 
+    struct msghdr *msg, struct netbsd32_msghdr *arg,
+    struct mbuf *from, struct mbuf *control)
+{
+	int error = 0;
+
+	if (msg->msg_control != NULL)
+		error = copyout32_msg_control(l, msg, control);
+
+	if (error == 0)
+		error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
+			from);
+
+	if (from != NULL)
+		m_free(from);
+	if (error)
+		return error;
+
+	msg32->msg_namelen = msg->msg_namelen;
+	msg32->msg_controllen = msg->msg_controllen;
+	msg32->msg_flags = msg->msg_flags;
+	ktrkuser("msghdr", msg, sizeof(*msg));
+	if (arg == NULL)
+		return 0;
+	return copyout(msg32, arg, sizeof(*arg));
+}
+
 int
 netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap,
     register_t *retval)
@@ -169,61 +225,144 @@ netbsd32_recvmsg(struct lwp *l, const st
 		syscallarg(int) flags;
 	} */
 	struct netbsd32_msghdr	msg32;
-	struct iovec aiov[UIO_SMALLIOV], *iov;
+	struct iovec aiov[UIO_SMALLIOV];
 	struct msghdr	msg;
 	int		error;
 	struct mbuf	*from, *control;
-	size_t iovsz;
 
 	error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
 	if (error)
 		return (error);
 
-	iovsz = msg32.msg_iovlen * sizeof(struct iovec);
-	if (msg32.msg_iovlen > UIO_SMALLIOV) {
-		if (msg32.msg_iovlen > IOV_MAX)
-			return (EMSGSIZE);
-		iov = kmem_alloc(iovsz, KM_SLEEP);
-	} else 
-		iov = aiov;
-	error = netbsd32_to_iovecin(NETBSD32PTR64(msg32.msg_iov), iov,
-	    msg32.msg_iovlen);
-	if (error)
-		goto done;
+	if ((error = msg_recv_copyin(l, &msg32, &msg, aiov)) != 0)
+		return error;
 
 	msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
-	msg.msg_name = NETBSD32PTR64(msg32.msg_name);
-	msg.msg_namelen = msg32.msg_namelen;
-	msg.msg_control = NETBSD32PTR64(msg32.msg_control);
-	msg.msg_controllen = msg32.msg_controllen;
-	msg.msg_iov = iov;
-	msg.msg_iovlen = msg32.msg_iovlen;
-
 	error = do_sys_recvmsg(l, SCARG(uap, s), &msg,
 	    &from, msg.msg_control != NULL ? &control : NULL, retval);
 	if (error != 0)
-		goto done;
+		goto out;
+
+	error = msg_recv_copyout(l, &msg32, &msg, SCARG_P32(uap, msg),
+	    from, control);
+out:
+	if (msg.msg_iov != aiov)
+		kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec));
+	return error;
+}
 
-	if (msg.msg_control != NULL)
-		error = copyout32_msg_control(l, &msg, control);
+int
+netbsd32_recvmmsg(struct lwp *l, const struct netbsd32_recvmmsg_args *uap,
+    register_t *retval)
+{
+	/* {
+		syscallarg(int)				s;
+		syscallarg(netbsd32_mmsghdr_t)		mmsg;
+		syscallarg(unsigned int)		vlen;
+		syscallarg(unsigned int)		flags;
+		syscallarg(netbsd32_timespecp_t)	timeout;
+	} */
+	struct mmsghdr mmsg;
+	struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg);
+	struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr;
+	struct socket *so;
+	struct msghdr *msg = &mmsg.msg_hdr;
+	int error, s;
+	struct mbuf *from, *control;
+	struct timespec ts, now;
+	struct netbsd32_timespec ts32;
+	unsigned int vlen, flags, dg;
+	struct iovec aiov[UIO_SMALLIOV];
+
+	ts.tv_sec = 0;	// XXX: gcc
+	ts.tv_nsec = 0;
+	if (SCARG_P32(uap, timeout)) {
+		if ((error = copyin(SCARG_P32(uap, timeout), &ts32,
+		    sizeof(ts32))) != 0)
+			return error;
+		getnanotime(&now);
+		netbsd32_to_timespec(&ts32, &ts);
+		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;
+
+	for (dg = 0; dg < vlen;) {
+		error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32));
+		if (error)
+			break;
+
+		if ((error = msg_recv_copyin(l, msg32, msg, aiov)) != 0)
+			return error;
+
+		msg->msg_flags = flags & ~MSG_WAITFORONE;
+
+		if (from != NULL) {
+			m_free(from);
+			from = NULL;
+		}
+
+		error = do_sys_recvmsg_so(l, s, so, msg, &from,
+		    msg->msg_control != NULL ? &control : NULL, retval);
+		if (error) {
+			if (error == EAGAIN && dg > 0)
+				error = 0;
+			break;
+		}
+		error = msg_recv_copyout(l, msg32, msg, NULL,
+		    from, control);
+		from = NULL;
+		if (error)
+			break;
+
+		mmsg32.msg_len = *retval;
+
+		error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32));
+		if (error)
+			break;
+
+		dg++;
+		if (msg->msg_flags & MSG_OOB)
+			break;
+
+		if (SCARG_P32(uap, timeout)) {
+			getnanotime(&now);
+			timespecsub(&now, &ts, &now);
+			if (now.tv_sec > 0)
+				break;
+		}
+
+		if (flags & MSG_WAITFORONE)
+			flags |= MSG_DONTWAIT;
+
+	}
 
-	if (error == 0)
-		error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
-			from);
 	if (from != NULL)
 		m_free(from);
-	if (error == 0) {
-		msg32.msg_namelen = msg.msg_namelen;
-		msg32.msg_controllen = msg.msg_controllen;
-		msg32.msg_flags = msg.msg_flags;
-		ktrkuser("msghdr", &msg, sizeof msg);
-		error = copyout(&msg32, SCARG_P32(uap, msg), sizeof(msg32));
-	}
 
- done:
-	if (iov != aiov)
-		kmem_free(iov, iovsz);
-	return (error);
+	*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;
 }
 
 static int
@@ -326,6 +465,50 @@ failure:
 	return error;
 }
 
+static int
+msg_send_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32,
+    struct msghdr *msg, struct iovec *aiov)
+{
+	int error;
+	struct iovec *iov = aiov;
+	struct netbsd32_iovec *iov32;
+	size_t iovsz;
+
+	netbsd32_to_msghdr(msg32, msg);
+	msg->msg_flags = 0;
+
+	if (CMSG32_FIRSTHDR(msg)) {
+		error = copyin32_msg_control(l, msg);
+		if (error)
+			return error;
+		/* From here on, msg->msg_control is allocated */
+	} else {
+		msg->msg_control = NULL;
+		msg->msg_controllen = 0;
+	}
+
+	iovsz = msg->msg_iovlen * sizeof(struct iovec);
+	if ((u_int)msg->msg_iovlen > UIO_SMALLIOV) {
+		if ((u_int)msg->msg_iovlen > IOV_MAX) {
+			error = EMSGSIZE;
+			goto out;
+		}
+		iov = kmem_alloc(iovsz, KM_SLEEP);
+	}
+
+	iov32 = NETBSD32PTR64(msg32->msg_iov);
+	error = netbsd32_to_iovecin(iov32, iov, msg->msg_iovlen);
+	if (error)
+		goto out;
+	msg->msg_iov = iov;
+out:
+	if (msg->msg_control)
+		m_free(msg->msg_control);
+	if (iov != aiov)
+		kmem_free(iov, iovsz);
+	return error;
+}
+
 int
 netbsd32_sendmsg(struct lwp *l, const struct netbsd32_sendmsg_args *uap,
     register_t *retval)
@@ -337,55 +520,93 @@ netbsd32_sendmsg(struct lwp *l, const st
 	} */
 	struct msghdr msg;
 	struct netbsd32_msghdr msg32;
-	struct iovec aiov[UIO_SMALLIOV], *iov = aiov;
-	struct netbsd32_iovec *iov32;
-	size_t iovsz;
+	struct iovec aiov[UIO_SMALLIOV];
 	int error;
 
 	error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
 	if (error)
-		return (error);
-	netbsd32_to_msghdr(&msg32, &msg);
-	msg.msg_flags = 0;
+		return error;
+
+	if ((error = msg_send_copyin(l, &msg32, &msg, aiov)) != 0)
+		return error;
+
+	error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
+	    retval);
+	/* msg.msg_control freed by do_sys_sendmsg() */
+
+	if (msg.msg_iov != aiov)
+		kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec));
+	return error;
+}
 
-	if (CMSG32_FIRSTHDR(&msg)) {
-		error = copyin32_msg_control(l, &msg);
+int
+netbsd32_sendmmsg(struct lwp *l, const struct netbsd32_sendmmsg_args *uap,
+    register_t *retval)
+{
+	/* {
+		syscallarg(int)			s;
+		syscallarg(const netbsd32_mmsghdr_t)	mmsg;
+		syscallarg(unsigned int)	vlen;
+		syscallarg(unsigned int)	flags;
+	} */
+	struct mmsghdr mmsg;
+	struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg);
+	struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr;
+	struct socket *so;
+	file_t *fp;
+	struct msghdr *msg = &mmsg.msg_hdr;
+	int error, s;
+	unsigned int vlen, flags, dg;
+	struct iovec aiov[UIO_SMALLIOV];
+
+	s = SCARG(uap, s);
+	if ((error = fd_getsock1(s, &so, &fp)) != 0)
+		return error;
+
+	vlen = SCARG(uap, vlen);
+	if (vlen > 1024)
+		vlen = 1024;
+
+	flags = SCARG(uap, flags) & MSG_USERFLAGS;
+
+	for (dg = 0; dg < vlen;) {
+		error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32));
 		if (error)
-			return (error);
-		/* From here on, msg.msg_control is allocated */
-	} else {
-		msg.msg_control = NULL;
-		msg.msg_controllen = 0;
-	}
+			break;
+		if ((error = msg_send_copyin(l, msg32, msg, aiov)) != 0)
+			break;
 
-	iovsz = msg.msg_iovlen * sizeof(struct iovec);
-	if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
-		if ((u_int)msg.msg_iovlen > IOV_MAX) {
-			error = EMSGSIZE;
-			goto out;
+		msg->msg_flags = flags;
+
+		error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
+		if (msg->msg_iov != aiov) {
+			kmem_free(msg->msg_iov,
+			    msg->msg_iovlen * sizeof(struct iovec));
 		}
-		iov = kmem_alloc(iovsz, KM_SLEEP);
+		if (error)
+			break;
+
+		ktrkuser("msghdr", msg, sizeof(*msg));
+		mmsg.msg_len = *retval;
+		netbsd32_from_mmsghdr(&mmsg32, &mmsg);
+		error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32));
+		if (error)
+			break;
+		dg++;
 	}
 
-	iov32 = NETBSD32PTR64(msg32.msg_iov);
-	error = netbsd32_to_iovecin(iov32, iov, msg.msg_iovlen);
+	*retval = dg;
 	if (error)
-		goto out;
-	msg.msg_iov = iov;
-
-	error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
-	    retval);
-	/* msg.msg_control freed by do_sys_sendmsg() */
+		so->so_error = error;
 
-	if (iov != aiov)
-		kmem_free(iov, iovsz);
-	return (error);
+	fd_putfile(s);
 
-out:
-	if (iov != aiov)
-		kmem_free(iov, iovsz);
-	if (msg.msg_control)
-		m_free(msg.msg_control);
+	/*
+	 * 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/netbsd32/syscalls.master
diff -u src/sys/compat/netbsd32/syscalls.master:1.120 src/sys/compat/netbsd32/syscalls.master:1.121
--- src/sys/compat/netbsd32/syscalls.master:1.120	Sat Jan  6 11:41:23 2018
+++ src/sys/compat/netbsd32/syscalls.master	Wed May  9 22:36:07 2018
@@ -1,4 +1,4 @@
-	$NetBSD: syscalls.master,v 1.120 2018/01/06 16:41:23 kamil Exp $
+	$NetBSD: syscalls.master,v 1.121 2018/05/10 02:36:07 christos Exp $
 
 ;	from: NetBSD: syscalls.master,v 1.81 1998/07/05 08:49:50 jonathan Exp
 ;	@(#)syscalls.master	8.2 (Berkeley) 1/13/94
@@ -1030,16 +1030,18 @@
 473	STD		{ int|netbsd32||__quotactl(const netbsd32_charp path, \
 			    netbsd32_voidp args); }
 474	NOERR		{ int|netbsd32||posix_spawn(netbsd32_pid_tp pid, \
-				const netbsd32_charp path, \
-				const netbsd32_posix_spawn_file_actionsp \
-				    file_actions, \
-				const netbsd32_posix_spawnattrp attrp, \
-				netbsd32_charpp argv, netbsd32_charpp envp); }
+			    const netbsd32_charp path, \
+			    const netbsd32_posix_spawn_file_actionsp \
+				file_actions, \
+			    const netbsd32_posix_spawnattrp attrp, \
+			    netbsd32_charpp argv, netbsd32_charpp envp); }
 
-475	UNIMPL		{ int|netbsd32||recvmmsg(int s, struct mmsghdr *mmsg, \
+475	STD		{ int|netbsd32||recvmmsg(int s, \
+			    netbsd32_mmsghdrp_t mmsg, \
 			    unsigned int vlen, unsigned int flags, \
 			    netbsd32_timespecp_t timeout); }
-476	UNIMPL		{ int|netbsd32||sendmmsg(int s, struct mmsghdr *mmsg, \
+476	STD		{ int|netbsd32||sendmmsg(int s, \
+			    netbsd32_mmsghdrp_t mmsg, \
 			    unsigned int vlen, unsigned int flags); }
 477	STD 		{ int|netbsd32||clock_nanosleep(\
 			    netbsd32_clockid_t clock_id, \

Reply via email to