I addressed your concerns as well as these of jca, just the kernel
part (and the new ktrace stuff) below.

One minor thing: I didn't see any kdump output where one struct was
contained in another one but I am printing it like ddb would so I
guess it should be fine.


Index: kern/syscalls.master
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.229
diff -u -p -r1.229 syscalls.master
--- kern/syscalls.master        1 Aug 2022 14:56:59 -0000       1.229
+++ kern/syscalls.master        1 Sep 2022 14:52:47 -0000
@@ -244,8 +244,10 @@
                            const char *permissions); }
 115    STD             { int sys___realpath(const char *pathname, \
                            char *resolved); }
-116    OBSOL           t32_gettimeofday
-117    OBSOL           t32_getrusage
+116    STD NOLOCK      { int sys_recvmmsg(int s, struct mmsghdr *mmsg, \
+                           unsigned int vlen, unsigned int flags, \
+                           struct timespec *timeout); }
+117    UNIMPL          sendmmsg
 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: kern/uipc_syscalls.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.201
diff -u -p -r1.201 uipc_syscalls.c
--- kern/uipc_syscalls.c        14 Aug 2022 01:58:28 -0000      1.201
+++ kern/uipc_syscalls.c        1 Sep 2022 14:37:26 -0000
@@ -805,6 +805,140 @@ done:
 }
 
 int
+sys_recvmmsg(struct proc *p, void *v, register_t *retval)
+{
+       struct sys_recvmmsg_args /* {
+               syscallarg(int)                 s;
+               syscallarg(struct mmsghdr *)    mmsg;
+               syscallarg(unsigned int)        vlen;
+               syscallarg(unsigned int)        flags;
+               syscallarg(struct timespec *)   timeout;
+       } */ *uap = v;
+       struct mmsghdr mmsg, *mmsgp;
+       struct timespec ts, now;
+       struct iovec aiov[UIO_SMALLIOV], *uiov, *iov = aiov;
+       struct file *fp;
+       struct socket *so;
+       struct timespec *timeout;
+       size_t iovlen = UIO_SMALLIOV;
+       register_t retrec;
+       unsigned int vlen, dgrams;
+       int error = 0, flags, s;
+
+       s = SCARG(uap, s);
+       if ((error = getsock(p, s, &fp)))
+               return (error);
+       so = (struct socket *)fp->f_data;
+
+       timeout = SCARG(uap, timeout);
+       if (timeout != NULL) {
+               error = copyin(timeout, &ts, sizeof(ts));
+               if (error)
+                       return error;
+#ifdef KTRACE
+               if (KTRPOINT(p, KTR_STRUCT))
+                       ktrreltimespec(p, &ts);
+#endif
+               getnanotime(&now);
+               timespecadd(&now, &ts, &ts);
+       }
+
+       flags = SCARG(uap, flags);
+
+       /* Arbitrarily capped at 1024 datagrams. */
+       vlen = SCARG(uap, vlen);
+       if (vlen > 1024)
+               vlen = 1024;
+
+       mmsgp = SCARG(uap, mmsg);
+       for (dgrams = 0; dgrams < vlen;) {
+               error = copyin(&mmsgp[dgrams], &mmsg, sizeof(mmsg));
+               if (error)
+                       break;
+
+               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;
+               }
+
+               uiov = mmsg.msg_hdr.msg_iov;
+               mmsg.msg_hdr.msg_iov = iov;
+               mmsg.msg_hdr.msg_flags = flags;
+
+               error = recvit(p, s, &mmsg.msg_hdr, NULL, &retrec);
+               if (error) {
+                       if (error == EAGAIN && dgrams > 0)
+                               error = 0;
+                       break;
+               }
+
+               if (dgrams == 0 && flags & MSG_WAITFORONE) {
+                       flags &= ~MSG_WAITFORONE;
+                       flags |= MSG_DONTWAIT;
+               }
+
+               mmsg.msg_hdr.msg_iov = uiov;
+               mmsg.msg_len = retrec;
+#ifdef KTRACE
+               if (KTRPOINT(p, KTR_STRUCT)) {
+                       ktrmmsghdr(p, &mmsg);
+                       if (mmsg.msg_hdr.msg_iovlen)
+                               ktriovec(p, iov, mmsg.msg_hdr.msg_iovlen);
+               }
+#endif
+
+               error = copyout(&mmsg, &mmsgp[dgrams], sizeof(mmsg));
+               if (error)
+                       break;
+
+               dgrams++;
+               if (mmsg.msg_hdr.msg_flags & MSG_OOB)
+                       break;
+
+               if (timeout != NULL) {
+                       getnanotime(&now);
+                       timespecsub(&now, &ts, &now);
+                       if (now.tv_sec > 0)
+                               break;
+               }
+       }
+
+       if (iov != aiov)
+               free(iov, M_IOV, iovlen * sizeof(struct iovec));
+
+       *retval = dgrams;
+
+       /*
+        * If we succeeded at least once, return 0, hopefully so->so_error
+        * will catch it next time.
+        */
+       if (error && dgrams > 0) {
+               so->so_error = error;
+               error = 0;
+       }
+
+       FRELE(fp, p);
+       return (error);
+}
+
+int
 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
     register_t *retsize)
 {
Index: sys/ktrace.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/sys/ktrace.h,v
retrieving revision 1.41
diff -u -p -r1.41 ktrace.h
--- sys/ktrace.h        22 Feb 2022 17:14:14 -0000      1.41
+++ sys/ktrace.h        1 Sep 2022 14:35:13 -0000
@@ -239,6 +239,8 @@ void    ktrstruct(struct proc *, const c
        ktrstruct((p), "quota", (s), sizeof(struct dqblk))
 #define ktrmsghdr(p, s) \
        ktrstruct(p, "msghdr", s, sizeof(struct msghdr))
+#define ktrmmsghdr(p, s) \
+       ktrstruct(p, "mmsghdr", s, sizeof(struct mmsghdr))
 #define ktriovec(p, s, count) \
        ktrstruct(p, "iovec", s, (count) * sizeof(struct iovec))
 #define ktrcmsghdr(p, c, len) \
Index: sys/socket.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/sys/socket.h,v
retrieving revision 1.102
diff -u -p -r1.102 socket.h
--- sys/socket.h        22 Feb 2022 01:01:02 -0000      1.102
+++ sys/socket.h        1 Sep 2022 08:49:48 -0000
@@ -490,6 +490,13 @@ struct msghdr {
        int             msg_flags;      /* flags on received message */
 };
 
+struct mmsghdr {
+       struct msghdr msg_hdr;
+       unsigned int msg_len;
+};
+
+struct timespec;
+
 #define        MSG_OOB                 0x1     /* process out-of-band data */
 #define        MSG_PEEK                0x2     /* peek at incoming message */
 #define        MSG_DONTROUTE           0x4     /* send without using routing 
tables */
@@ -502,6 +509,7 @@ struct msghdr {
 #define        MSG_MCAST               0x200   /* this message rec'd as 
multicast */
 #define        MSG_NOSIGNAL            0x400   /* do not send SIGPIPE */
 #define        MSG_CMSG_CLOEXEC        0x800   /* set FD_CLOEXEC on received 
fds */
+#define        MSG_WAITFORONE          0x1000  /* nonblocking but wait for one 
msg */
 
 /*
  * Header for ancillary data objects in msg_control buffer.
@@ -565,6 +573,8 @@ int listen(int, int);
 ssize_t        recv(int, void *, size_t, int);
 ssize_t        recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t 
*);
 ssize_t        recvmsg(int, struct msghdr *, int);
+int    recvmmsg(int, struct mmsghdr *, unsigned int, unsigned int,
+           struct timespec *);
 ssize_t        send(int, const void *, size_t, int);
 ssize_t        sendto(int, const void *,
            size_t, int, const struct sockaddr *, socklen_t);
Index: usr.bin/kdump/kdump.c
===================================================================
RCS file: /mount/openbsd/cvs/src/usr.bin/kdump/kdump.c,v
retrieving revision 1.149
diff -u -p -r1.149 kdump.c
--- usr.bin/kdump/kdump.c       20 Jul 2022 05:56:36 -0000      1.149
+++ usr.bin/kdump/kdump.c       1 Sep 2022 15:03:03 -0000
@@ -795,6 +795,7 @@ static const formatter scargs[][8] = {
     [SYS_ppoll]                = { Pptr, Pucount, Pptr, Pptr },
     [SYS_pselect]      = { Pcount, Pptr, Pptr, Pptr, Pptr, Pptr },
     [SYS_sigsuspend]   = { Sigset },
+    [SYS_recvmmsg]     = { Pfd, Pptr, Pcount, Sendrecvflagsname, Pptr },
     [SYS_getsockopt]   = { Pfd, PASS_TWO, Sockoptlevelname, Pptr, Pptr },
     [SYS_thrkill]      = { Ppid_t, Signame, Pptr },
     [SYS_readv]                = { Pfd, Pptr, Pcount },
Index: usr.bin/kdump/ktrstruct.c
===================================================================
RCS file: /mount/openbsd/cvs/src/usr.bin/kdump/ktrstruct.c,v
retrieving revision 1.29
diff -u -p -r1.29 ktrstruct.c
--- usr.bin/kdump/ktrstruct.c   21 Dec 2020 07:47:37 -0000      1.29
+++ usr.bin/kdump/ktrstruct.c   1 Sep 2022 15:24:42 -0000
@@ -398,6 +398,18 @@ ktrquota(const struct dqblk *quota)
 }
 
 static void
+ktrmmsghdr(const struct mmsghdr *mmsg)
+{
+       printf("struct mmsghdr { msg_hdr = { name=%p, namelen=%u, iov=%p, 
iovlen=%u,"
+           " control=%p, controllen=%u, flags=",
+           mmsg->msg_hdr.msg_name, mmsg->msg_hdr.msg_namelen,
+           mmsg->msg_hdr.msg_iov, mmsg->msg_hdr.msg_iovlen,
+           mmsg->msg_hdr.msg_control, mmsg->msg_hdr.msg_controllen);
+       sendrecvflagsname(mmsg->msg_hdr.msg_flags);
+       printf(" }, msg_len = %u }\n", mmsg->msg_len);
+}
+
+static void
 ktrmsghdr(const struct msghdr *msg)
 {
        printf("struct msghdr { name=%p, namelen=%u, iov=%p, iovlen=%u,"
@@ -649,6 +661,13 @@ ktrstruct(char *buf, size_t buflen)
                        goto invalid;
                memcpy(&msg, data, datalen);
                ktrmsghdr(&msg);
+       } else if (strcmp(name, "mmsghdr") == 0) {
+               struct mmsghdr mmsg;
+
+               if (datalen != sizeof(mmsg))
+                       goto invalid;
+               memcpy(&mmsg, data, datalen);
+               ktrmmsghdr(&mmsg);
        } else if (strcmp(name, "iovec") == 0) {
                if (datalen % sizeof(struct iovec))
                        goto invalid;

Reply via email to