From 94bc6e282f5b07d1de39ef73346b4eb06b2a5ea6 Mon Sep 17 00:00:00 2001 From: mbuhl Date: Sat, 3 Sep 2022 12:33:44 +0000 Subject: [PATCH] add the sendmmsg syscall that allows sending multiple msghdrs at once. libc, man page, and regress parts to come. With input from jca@, bluhm@. OK bluhm@ --- sys/kern/init_sysent.c | 6 +-- sys/kern/syscalls.c | 4 +- sys/kern/syscalls.master | 6 ++- sys/kern/uipc_syscalls.c | 88 +++++++++++++++++++++++++++++++++++++++- sys/sys/socket.h | 3 +- sys/sys/syscall.h | 5 ++- sys/sys/syscallargs.h | 10 ++++- 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 59dd3aded35..7e2cc3661d1 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -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, diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 9f3b973e005..2cddcb6a538 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -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 */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index eaf34dfabfe..9d88bf30dc1 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -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 @@ -247,7 +247,9 @@ 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); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index b68e8534048..02a36683b9f 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -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) { diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 35758827b30..06def618354 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -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); diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index 3965289efb4..c2ad6f36256 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -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. @@ -355,6 +355,9 @@ /* 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 diff --git a/sys/sys/syscallargs.h b/sys/sys/syscallargs.h index c0559a0502f..5b20dce89e3 100644 --- a/sys/sys/syscallargs.h +++ b/sys/sys/syscallargs.h @@ -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 *); -- 2.20.1