add the sendmmsg syscall that allows sending multiple msghdrs at
authormbuhl <mbuhl@openbsd.org>
Sat, 3 Sep 2022 12:33:44 +0000 (12:33 +0000)
committermbuhl <mbuhl@openbsd.org>
Sat, 3 Sep 2022 12:33:44 +0000 (12:33 +0000)
once. libc, man page, and regress parts to come.
With input from jca@, bluhm@.
OK bluhm@

sys/kern/init_sysent.c
sys/kern/syscalls.c
sys/kern/syscalls.master
sys/kern/uipc_syscalls.c
sys/sys/socket.h
sys/sys/syscall.h
sys/sys/syscallargs.h

index 59dd3ad..7e2cc36 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: init_sysent.c,v 1.245 2022/09/02 13:23:33 mbuhl Exp $ */
+/*     $OpenBSD: init_sysent.c,v 1.246 2022/09/03 12:33:44 mbuhl Exp $ */
 
 /*
  * System call switch table.
@@ -266,8 +266,8 @@ const struct sysent sysent[] = {
            sys___realpath },                   /* 115 = __realpath */
        { 5, s(struct sys_recvmmsg_args), SY_NOLOCK | 0,
            sys_recvmmsg },                     /* 116 = recvmmsg */
-       { 0, 0, 0,
-           sys_nosys },                        /* 117 = unimplemented sendmmsg */
+       { 4, s(struct sys_sendmmsg_args), SY_NOLOCK | 0,
+           sys_sendmmsg },                     /* 117 = sendmmsg */
        { 5, s(struct sys_getsockopt_args), 0,
            sys_getsockopt },                   /* 118 = getsockopt */
        { 3, s(struct sys_thrkill_args), 0,
index 9f3b973..2cddcb6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscalls.c,v 1.243 2022/09/02 13:23:33 mbuhl Exp $    */
+/*     $OpenBSD: syscalls.c,v 1.244 2022/09/03 12:33:44 mbuhl Exp $    */
 
 /*
  * System call names.
@@ -137,7 +137,7 @@ const char *const syscallnames[] = {
        "unveil",                       /* 114 = unveil */
        "__realpath",                   /* 115 = __realpath */
        "recvmmsg",                     /* 116 = recvmmsg */
-       "#117 (unimplemented sendmmsg)",                /* 117 = unimplemented sendmmsg */
+       "sendmmsg",                     /* 117 = sendmmsg */
        "getsockopt",                   /* 118 = getsockopt */
        "thrkill",                      /* 119 = thrkill */
        "readv",                        /* 120 = readv */
index eaf34df..9d88bf3 100644 (file)
@@ -1,4 +1,4 @@
-;      $OpenBSD: syscalls.master,v 1.230 2022/09/02 13:18:06 mbuhl Exp $
+;      $OpenBSD: syscalls.master,v 1.231 2022/09/03 12:33:44 mbuhl Exp $
 ;      $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $
 
 ;      @(#)syscalls.master     8.2 (Berkeley) 1/13/94
 116    STD NOLOCK      { int sys_recvmmsg(int s, struct mmsghdr *mmsg, \
                            unsigned int vlen, unsigned int flags, \
                            struct timespec *timeout); }
-117    UNIMPL          sendmmsg
+117    STD NOLOCK      { int sys_sendmmsg(int s,  \
+                           struct mmsghdr *mmsg, unsigned int vlen, \
+                           unsigned int flags); }
 118    STD             { int sys_getsockopt(int s, int level, int name, \
                            void *val, socklen_t *avalsize); }
 119    STD             { int sys_thrkill(pid_t tid, int signum, void *tcb); }
index b68e853..02a3668 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_syscalls.c,v 1.202 2022/09/02 13:18:06 mbuhl Exp $       */
+/*     $OpenBSD: uipc_syscalls.c,v 1.203 2022/09/03 12:33:44 mbuhl Exp $       */
 /*     $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $      */
 
 /*
@@ -605,6 +605,92 @@ done:
        return (error);
 }
 
+int
+sys_sendmmsg(struct proc *p, void *v, register_t *retval)
+{
+       struct sys_sendmmsg_args /* {
+               syscallarg(int)                 s;
+               syscallarg(struct mmsghdr *)    mmsg;
+               syscallarg(unsigned int)        vlen;
+               syscallarg(unsigned int)        flags;
+       } */ *uap = v;
+       struct mmsghdr mmsg, *mmsgp;
+       struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *uiov;
+       size_t iovlen = UIO_SMALLIOV;
+       register_t retsnd;
+       unsigned int vlen, dgrams;
+       int error = 0;
+
+       /* Arbitrarily capped at 1024 datagrams. */
+       vlen = SCARG(uap, vlen);
+       if (vlen > 1024)
+               vlen = 1024;
+
+       mmsgp = SCARG(uap, mmsg);
+       for (dgrams = 0; dgrams < vlen; dgrams++) {
+               error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
+               if (error)
+                       break;
+
+#ifdef KTRACE
+               if (KTRPOINT(p, KTR_STRUCT))
+                       ktrmmsghdr(p, &mmsg);
+#endif
+
+               if (mmsg.msg_hdr.msg_iovlen > IOV_MAX) {
+                       error = EMSGSIZE;
+                       break;
+               }
+
+               if (mmsg.msg_hdr.msg_iovlen > iovlen) {
+                       if (iov != aiov)
+                               free(iov, M_IOV, iovlen *
+                                   sizeof(struct iovec));
+
+                       iovlen = mmsg.msg_hdr.msg_iovlen;
+                       iov = mallocarray(iovlen, sizeof(struct iovec),
+                           M_IOV, M_WAITOK);
+               }
+
+               if (mmsg.msg_hdr.msg_iovlen > 0) {
+                       error = copyin(mmsg.msg_hdr.msg_iov, iov,
+                           mmsg.msg_hdr.msg_iovlen * sizeof(struct iovec));
+                       if (error)
+                               break;
+               }
+
+#ifdef KTRACE
+               if (mmsg.msg_hdr.msg_iovlen && KTRPOINT(p, KTR_STRUCT))
+                       ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
+#endif
+
+               uiov = mmsg.msg_hdr.msg_iov;
+               mmsg.msg_hdr.msg_iov = iov;
+               mmsg.msg_hdr.msg_flags = 0;
+
+               error = sendit(p, SCARG(uap, s), &mmsg.msg_hdr,
+                   SCARG(uap, flags), &retsnd);
+               if (error)
+                       break;
+
+               mmsg.msg_hdr.msg_iov = uiov;
+               mmsg.msg_len = retsnd;
+
+               error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
+               if (error)
+                       break;
+       }
+
+       if (iov != aiov)
+               free(iov, M_IOV, sizeof(struct iovec) * iovlen);
+
+       *retval = dgrams;
+
+       if (dgrams)
+               return 0;
+       return error;
+}
+
 int
 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
 {
index 3575882..06def61 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: socket.h,v 1.103 2022/09/02 13:18:07 mbuhl Exp $      */
+/*     $OpenBSD: socket.h,v 1.104 2022/09/03 12:33:45 mbuhl Exp $      */
 /*     $NetBSD: socket.h,v 1.14 1996/02/09 18:25:36 christos Exp $     */
 
 /*
@@ -579,6 +579,7 @@ ssize_t     send(int, const void *, size_t, int);
 ssize_t        sendto(int, const void *,
            size_t, int, const struct sockaddr *, socklen_t);
 ssize_t        sendmsg(int, const struct msghdr *, int);
+int    sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int);
 int    setsockopt(int, int, int, const void *, socklen_t);
 int    shutdown(int, int);
 int    sockatmark(int);
index 3965289..c2ad6f3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscall.h,v 1.242 2022/09/02 13:23:33 mbuhl Exp $     */
+/*     $OpenBSD: syscall.h,v 1.243 2022/09/03 12:33:45 mbuhl Exp $     */
 
 /*
  * System call numbers.
 /* syscall: "recvmmsg" ret: "int" args: "int" "struct mmsghdr *" "unsigned int" "unsigned int" "struct timespec *" */
 #define        SYS_recvmmsg    116
 
+/* syscall: "sendmmsg" ret: "int" args: "int" "struct mmsghdr *" "unsigned int" "unsigned int" */
+#define        SYS_sendmmsg    117
+
 /* syscall: "getsockopt" ret: "int" args: "int" "int" "int" "void *" "socklen_t *" */
 #define        SYS_getsockopt  118
 
index c0559a0..5b20dce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscallargs.h,v 1.245 2022/09/02 13:23:33 mbuhl Exp $ */
+/*     $OpenBSD: syscallargs.h,v 1.246 2022/09/03 12:33:45 mbuhl Exp $ */
 
 /*
  * System call argument lists.
@@ -603,6 +603,13 @@ struct sys_recvmmsg_args {
        syscallarg(struct timespec *) timeout;
 };
 
+struct sys_sendmmsg_args {
+       syscallarg(int) s;
+       syscallarg(struct mmsghdr *) mmsg;
+       syscallarg(unsigned int) vlen;
+       syscallarg(unsigned int) flags;
+};
+
 struct sys_getsockopt_args {
        syscallarg(int) s;
        syscallarg(int) level;
@@ -1311,6 +1318,7 @@ int       sys_sendsyslog(struct proc *, void *, register_t *);
 int    sys_unveil(struct proc *, void *, register_t *);
 int    sys___realpath(struct proc *, void *, register_t *);
 int    sys_recvmmsg(struct proc *, void *, register_t *);
+int    sys_sendmmsg(struct proc *, void *, register_t *);
 int    sys_getsockopt(struct proc *, void *, register_t *);
 int    sys_thrkill(struct proc *, void *, register_t *);
 int    sys_readv(struct proc *, void *, register_t *);