This adds a new API to do multishot recvmsg. This is more complicated than multishot recv as it requires handling a well known data layout copied by the kernel. Signed-off-by: Dylan Yudaken <dylany@xxxxxx> --- src/include/liburing.h | 59 +++++++++++++++++++++++++++++++++ src/include/liburing/io_uring.h | 7 ++++ 2 files changed, 66 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index d35bfa9..3f18bd2 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -419,6 +419,13 @@ static inline void io_uring_prep_recvmsg(struct io_uring_sqe *sqe, int fd, sqe->msg_flags = flags; } +static inline void io_uring_prep_recvmsg_multishot(struct io_uring_sqe *sqe, int fd, + struct msghdr *msg, unsigned flags) +{ + io_uring_prep_recvmsg(sqe, fd, msg, flags); + sqe->ioprio |= IORING_RECV_MULTISHOT; +} + static inline void io_uring_prep_sendmsg(struct io_uring_sqe *sqe, int fd, const struct msghdr *msg, unsigned flags) @@ -685,6 +692,58 @@ static inline void io_uring_prep_recv_multishot(struct io_uring_sqe *sqe, sqe->ioprio |= IORING_RECV_MULTISHOT; } +static inline struct io_uring_recvmsg_out *io_uring_recvmsg_validate( + void *buf, int buf_len, struct msghdr *m) +{ + struct io_uring_recvmsg_out *ret; + size_t header = m->msg_controllen + m->msg_namelen + sizeof(struct io_uring_recvmsg_out); + + if (buf_len < header) + return NULL; + ret = (struct io_uring_recvmsg_out *)buf; + if (buf_len < header + ret->payloadlen) + return NULL; + return ret; +} + +static inline void *io_uring_recvmsg_name(struct io_uring_recvmsg_out *o) +{ + return (void*)&o[1]; +} + +static inline struct cmsghdr *io_uring_recvmsg_cmsg_firsthdr(struct io_uring_recvmsg_out *o, + struct msghdr *m) +{ + if (o->controllen < sizeof(struct cmsghdr)) + return NULL; + return (struct cmsghdr *)((unsigned char*)io_uring_recvmsg_name(o) + m->msg_namelen); +} + +static inline void *io_uring_recvmsg_payload(struct io_uring_recvmsg_out *o, + struct msghdr *m) +{ + return (void*)((unsigned char*)io_uring_recvmsg_name(o) + m->msg_namelen + m->msg_controllen); +} + +static inline struct cmsghdr *io_uring_recvmsg_cmsg_nexthdr(struct io_uring_recvmsg_out *o, + struct msghdr *m, + struct cmsghdr *cmsg) +{ + unsigned char *end; + + if (cmsg->cmsg_len < sizeof (struct cmsghdr)) + return NULL; + end = (unsigned char *)io_uring_recvmsg_payload(o, m); + cmsg = (struct cmsghdr *)((unsigned char *)cmsg + CMSG_ALIGN(cmsg->cmsg_len)); + + if ((unsigned char *)(cmsg + 1) > end) + return NULL; + if (((unsigned char *)cmsg) + CMSG_ALIGN(cmsg->cmsg_len) > end) + return NULL; + + return cmsg; +} + static inline void io_uring_prep_openat2(struct io_uring_sqe *sqe, int dfd, const char *path, struct open_how *how) { diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index fbf6403..5e111b4 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -573,6 +573,13 @@ struct io_uring_file_index_range { __u64 resv; }; +struct io_uring_recvmsg_out { + __u32 namelen; + __u32 controllen; + __u32 payloadlen; + __u32 flags; +}; + /* * accept flags stored in sqe->ioprio */ -- 2.30.2