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, \