From 3efb381db2a44546a47e654bad714a81d646c38c Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Fri, 17 Jun 2022 12:31:57 +0200 Subject: [PATCH 1/3] swrap: Wrap sendmmsg() Recent bind9 versions use libuv internally and uv_udp_send() ends invoking the SYS_sendmmsg syscall directly on systems supporting it. The uid_wrapper will catch the syscall and invoke the libc wrapper. Signed-off-by: Samuel Cabrero --- src/socket_wrapper.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index ec8321f..19ec5ee 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -539,6 +539,7 @@ typedef int (*__libc_recvfrom)(int sockfd, typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags); typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags); typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags); +typedef int (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags); typedef int (*__libc_sendto)(int sockfd, const void *buf, size_t len, @@ -607,6 +608,7 @@ struct swrap_libc_symbols { SWRAP_SYMBOL_ENTRY(recvmsg); SWRAP_SYMBOL_ENTRY(send); SWRAP_SYMBOL_ENTRY(sendmsg); + SWRAP_SYMBOL_ENTRY(sendmmsg); SWRAP_SYMBOL_ENTRY(sendto); SWRAP_SYMBOL_ENTRY(setsockopt); #ifdef HAVE_SIGNALFD @@ -1246,6 +1248,7 @@ static void __swrap_bind_symbol_all_once(void) swrap_bind_symbol_libsocket(recvmsg); swrap_bind_symbol_libsocket(send); swrap_bind_symbol_libsocket(sendmsg); + swrap_bind_symbol_libsocket(sendmmsg); swrap_bind_symbol_libsocket(sendto); swrap_bind_symbol_libsocket(setsockopt); #ifdef HAVE_SIGNALFD @@ -7287,6 +7290,38 @@ ssize_t sendmsg(int s, const struct msghdr *omsg, int flags) return swrap_sendmsg(s, omsg, flags); } +/**************************************************************************** + * SENDMMSG + ***************************************************************************/ + +static int swrap_sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags) +{ + unsigned int i; + + SWRAP_LOG(SWRAP_LOG_DEBUG, "%s: vlen=%u\n", __func__, vlen); + + for (i=0; imsg_hdr; + ssize_t ret; + + ret = swrap_sendmsg(s, msg, flags); + SWRAP_LOG(SWRAP_LOG_DEBUG, "%s: msg[%i] sent, ret=%zd\n", + __func__, i, ret); + if (ret == -1) { + return -1; + } + mmsg->msg_len = ret; + } + + return i; +} + +int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags) +{ + return swrap_sendmmsg(s, msgvec, vlen, flags); +} + /**************************************************************************** * READV ***************************************************************************/ @@ -7881,6 +7916,7 @@ SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom); SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg); SWRAP_SYMBOL_ALIAS(send, _send); SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg); +SWRAP_SYMBOL_ALIAS(sendmmsg, _sendmmsg); SWRAP_SYMBOL_ALIAS(sendto, _sendto); SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt); SWRAP_SYMBOL_ALIAS(socket, _socket); -- GitLab From 99f3ae57a60a242f519ec17f502e7f2af4fb507f Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Fri, 17 Jun 2022 12:34:15 +0200 Subject: [PATCH 2/3] swrap: Wrap recvmmsg() Recent bind9 versions use libuv internally and uv_udp_send() ends invoking the SYS_recvmmsg syscall directly on systems supporting it. The uid_wrapper will catch the syscall and invoke the libc wrapper. The timeout argument is not implemented. Signed-off-by: Samuel Cabrero --- src/socket_wrapper.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 19ec5ee..0173eb9 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -540,6 +540,7 @@ typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags); typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags); typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags); typedef int (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags); +typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout); typedef int (*__libc_sendto)(int sockfd, const void *buf, size_t len, @@ -609,6 +610,7 @@ struct swrap_libc_symbols { SWRAP_SYMBOL_ENTRY(send); SWRAP_SYMBOL_ENTRY(sendmsg); SWRAP_SYMBOL_ENTRY(sendmmsg); + SWRAP_SYMBOL_ENTRY(recvmmsg); SWRAP_SYMBOL_ENTRY(sendto); SWRAP_SYMBOL_ENTRY(setsockopt); #ifdef HAVE_SIGNALFD @@ -1249,6 +1251,7 @@ static void __swrap_bind_symbol_all_once(void) swrap_bind_symbol_libsocket(send); swrap_bind_symbol_libsocket(sendmsg); swrap_bind_symbol_libsocket(sendmmsg); + swrap_bind_symbol_libsocket(recvmmsg); swrap_bind_symbol_libsocket(sendto); swrap_bind_symbol_libsocket(setsockopt); #ifdef HAVE_SIGNALFD @@ -7322,6 +7325,47 @@ int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags) return swrap_sendmmsg(s, msgvec, vlen, flags); } +/**************************************************************************** + * RECVMMSG + ***************************************************************************/ + +static int swrap_recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags, + struct timespec *timeout) +{ + unsigned int i; + + SWRAP_LOG(SWRAP_LOG_DEBUG, "%s: vlen=%u\n", __func__, vlen); + + if (timeout != NULL) { + SWRAP_LOG(SWRAP_LOG_ERROR, "%s: timeout arg not supported\n", __func__); + errno = ENOSYS; + return -1; + } + + for (i=0; imsg_hdr; + ssize_t ret; + + ret = swrap_recvmsg(s, msg, flags); + SWRAP_LOG(SWRAP_LOG_DEBUG, "%s: msg[%i] received, ret=%zd\n", + __func__, i, ret); + if (ret == -1) { + return -1; + } + mmsg->msg_len = ret; + + } + + return i; +} + +int recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags, + struct timespec *timeout) +{ + return swrap_recvmmsg(s, msgvec, vlen, flags, timeout); +} + /**************************************************************************** * READV ***************************************************************************/ @@ -7917,6 +7961,7 @@ SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg); SWRAP_SYMBOL_ALIAS(send, _send); SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg); SWRAP_SYMBOL_ALIAS(sendmmsg, _sendmmsg); +SWRAP_SYMBOL_ALIAS(recvmmsg, _recvmmsg); SWRAP_SYMBOL_ALIAS(sendto, _sendto); SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt); SWRAP_SYMBOL_ALIAS(socket, _socket); -- GitLab From 44af22ef83c68ac86c6ffa2de57eb3ce3da9a4cb Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Fri, 17 Jun 2022 14:13:15 +0200 Subject: [PATCH 3/3] cmake: Check recvmmsg() prototipe Signed-off-by: Samuel Cabrero --- ConfigureChecks.cmake | 8 ++++++++ config.h.cmake | 1 + src/socket_wrapper.c | 16 +++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 2c78b83..7de9325 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -147,6 +147,14 @@ if (HAVE_EVENTFD) HAVE_EVENTFD_UNSIGNED_INT) endif (HAVE_EVENTFD) +set(CMAKE_REQUIRED_FLAGS -D_GNU_SOURCE) +check_prototype_definition(recvmmsg + "int recvmmsg (int __fd, struct mmsghdr *__vmessages, unsigned int __vlen, int __flags, const struct timespec *__tmo)" + "-1" + "sys/socket.h" + HAVE_RECVMMSG_CONST_TIMEOUT) +unset(CMAKE_REQUIRED_FLAGS) + # IPV6 check_c_source_compiles(" #include diff --git a/config.h.cmake b/config.h.cmake index 0f2fb09..5c15a1f 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -52,6 +52,7 @@ #cmakedefine HAVE_ACCEPT_PSOCKLEN_T 1 #cmakedefine HAVE_IOCTL_INT 1 #cmakedefine HAVE_EVENTFD_UNSIGNED_INT 1 +#cmakedefine HAVE_RECVMMSG_CONST_TIMEOUT 1 /*************************** LIBRARIES ***************************/ diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 0173eb9..8865c91 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -540,7 +540,11 @@ typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags); typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags); typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags); typedef int (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags); +#if defined(HAVE_RECVMMSG_CONST_TIMEOUT) +typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout); +#else typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout); +#endif typedef int (*__libc_sendto)(int sockfd, const void *buf, size_t len, @@ -7329,8 +7333,13 @@ int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags) * RECVMMSG ***************************************************************************/ +#if defined(HAVE_RECVMMSG_CONST_TIMEOUT) +static int swrap_recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags, + const struct timespec *timeout) +#else static int swrap_recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) +#endif { unsigned int i; @@ -7360,8 +7369,13 @@ static int swrap_recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int return i; } +#if defined(HAVE_RECVMMSG_CONST_TIMEOUT) int recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags, - struct timespec *timeout) + const struct timespec *timeout) +#else +extern int recvmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, + int flags, struct timespec *timeout) +#endif { return swrap_recvmmsg(s, msgvec, vlen, flags, timeout); } -- GitLab