once. libc, man page, and regress parts to come.
With input from jca@, guenther@, bluhm@.
OK bluhm@
-/* $OpenBSD: init_sysent.c,v 1.243 2022/08/01 14:57:19 deraadt Exp $ */
+/* $OpenBSD: init_sysent.c,v 1.244 2022/09/02 13:18:06 mbuhl Exp $ */
/*
* System call switch table.
sys_unveil }, /* 114 = unveil */
{ 2, s(struct sys___realpath_args), 0,
sys___realpath }, /* 115 = __realpath */
+ { 5, s(struct sys_recvmmsg_args), SY_NOLOCK | 0,
+ sys_recvmmsg }, /* 116 = recvmmsg */
{ 0, 0, 0,
- sys_nosys }, /* 116 = obsolete t32_gettimeofday */
- { 0, 0, 0,
- sys_nosys }, /* 117 = obsolete t32_getrusage */
+ sys_nosys }, /* 117 = unimplemented sendmmsg */
{ 5, s(struct sys_getsockopt_args), 0,
sys_getsockopt }, /* 118 = getsockopt */
{ 3, s(struct sys_thrkill_args), 0,
-/* $OpenBSD: syscalls.c,v 1.241 2022/08/01 14:57:19 deraadt Exp $ */
+/* $OpenBSD: syscalls.c,v 1.242 2022/09/02 13:18:06 mbuhl Exp $ */
/*
* System call names.
"#113 (unimplemented fktrace)", /* 113 = unimplemented fktrace */
"unveil", /* 114 = unveil */
"__realpath", /* 115 = __realpath */
- "#116 (obsolete t32_gettimeofday)", /* 116 = obsolete t32_gettimeofday */
- "#117 (obsolete t32_getrusage)", /* 117 = obsolete t32_getrusage */
+ "recvmmsg", /* 116 = recvmmsg */
+ "#117 (unimplemented sendmmsg)", /* 117 = unimplemented sendmmsg */
"getsockopt", /* 118 = getsockopt */
"thrkill", /* 119 = thrkill */
"readv", /* 120 = readv */
-; $OpenBSD: syscalls.master,v 1.229 2022/08/01 14:56:59 deraadt Exp $
+; $OpenBSD: syscalls.master,v 1.230 2022/09/02 13:18:06 mbuhl Exp $
; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
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); }
-/* $OpenBSD: uipc_syscalls.c,v 1.201 2022/08/14 01:58:28 jsg Exp $ */
+/* $OpenBSD: uipc_syscalls.c,v 1.202 2022/09/02 13:18:06 mbuhl Exp $ */
/* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
/*
return (error);
}
+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)
-/* $OpenBSD: ktrace.h,v 1.41 2022/02/22 17:14:14 deraadt Exp $ */
+/* $OpenBSD: ktrace.h,v 1.42 2022/09/02 13:18:07 mbuhl Exp $ */
/* $NetBSD: ktrace.h,v 1.12 1996/02/04 02:12:29 christos Exp $ */
/*
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) \
-/* $OpenBSD: socket.h,v 1.102 2022/02/22 01:01:02 guenther Exp $ */
+/* $OpenBSD: socket.h,v 1.103 2022/09/02 13:18:07 mbuhl Exp $ */
/* $NetBSD: socket.h,v 1.14 1996/02/09 18:25:36 christos Exp $ */
/*
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 */
#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.
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);
-/* $OpenBSD: syscall.h,v 1.240 2022/08/01 14:57:19 deraadt Exp $ */
+/* $OpenBSD: syscall.h,v 1.241 2022/09/02 13:18:07 mbuhl Exp $ */
/*
* System call numbers.
/* syscall: "__realpath" ret: "int" args: "const char *" "char *" */
#define SYS___realpath 115
- /* 116 is obsolete t32_gettimeofday */
- /* 117 is obsolete t32_getrusage */
+/* syscall: "recvmmsg" ret: "int" args: "int" "struct mmsghdr *" "unsigned int" "unsigned int" "struct timespec *" */
+#define SYS_recvmmsg 116
+
/* syscall: "getsockopt" ret: "int" args: "int" "int" "int" "void *" "socklen_t *" */
#define SYS_getsockopt 118
-/* $OpenBSD: syscallargs.h,v 1.243 2022/08/01 14:57:19 deraadt Exp $ */
+/* $OpenBSD: syscallargs.h,v 1.244 2022/09/02 13:18:07 mbuhl Exp $ */
/*
* System call argument lists.
syscallarg(char *) resolved;
};
+struct sys_recvmmsg_args {
+ syscallarg(int) s;
+ syscallarg(struct mmsghdr *) mmsg;
+ syscallarg(unsigned int) vlen;
+ syscallarg(unsigned int) flags;
+ syscallarg(struct timespec *) timeout;
+};
+
struct sys_getsockopt_args {
syscallarg(int) s;
syscallarg(int) level;
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_getsockopt(struct proc *, void *, register_t *);
int sys_thrkill(struct proc *, void *, register_t *);
int sys_readv(struct proc *, void *, register_t *);