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/192eac36e666
branches:  trunk
changeset: 821401:192eac36e666
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 fd55765a2cd9 -r 192eac36e666 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), &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;
+}
diff -r fd55765a2cd9 -r 192eac36e666 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 fd55765a2cd9 -r 192eac36e666 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 fd55765a2cd9 -r 192eac36e666 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