From f7bc47a26f855fd7f0b1691f72973878f6cf7d1d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 13 Oct 2022 10:45:04 +0200 Subject: [PATCH] glib-aux: add nm_fd_next_datagram_size() helper --- src/libnm-glib-aux/nm-io-utils.c | 40 ++++++++++++++++++++++++++++++++ src/libnm-glib-aux/nm-io-utils.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/src/libnm-glib-aux/nm-io-utils.c b/src/libnm-glib-aux/nm-io-utils.c index 0823a16c42..b4bf30a8d4 100644 --- a/src/libnm-glib-aux/nm-io-utils.c +++ b/src/libnm-glib-aux/nm-io-utils.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "nm-str-buf.h" #include "nm-shared-utils.h" @@ -496,6 +497,45 @@ nm_utils_fd_read(int fd, NMStrBuf *out_string) /*****************************************************************************/ +/* Taken from systemd's next_datagram_size_fd(). */ +gssize +nm_fd_next_datagram_size(int fd) +{ + gssize l; + int k; + + /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will + * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't + * do. This difference is actually of major importance as we need to be sure that the size returned here + * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of + * the wrong size. */ + + l = recv(fd, NULL, 0, MSG_PEEK | MSG_TRUNC); + if (l < 0) { + if (NM_IN_SET(errno, EOPNOTSUPP, EFAULT)) + goto fallback; + + return -errno; + } + if (l == 0) + goto fallback; + + return l; + +fallback: + k = 0; + + /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD + * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */ + + if (ioctl(fd, FIONREAD, &k) < 0) + return -errno; + + return (gssize) k; +} + +/*****************************************************************************/ + typedef struct { GSubprocess *subprocess; GSource *timeout_source; diff --git a/src/libnm-glib-aux/nm-io-utils.h b/src/libnm-glib-aux/nm-io-utils.h index ef015153ca..f844c2125f 100644 --- a/src/libnm-glib-aux/nm-io-utils.h +++ b/src/libnm-glib-aux/nm-io-utils.h @@ -52,6 +52,8 @@ struct _NMStrBuf; gssize nm_utils_fd_read(int fd, struct _NMStrBuf *out_string); +gssize nm_fd_next_datagram_size(int fd); + struct stat; int nm_utils_file_stat(const char *filename, struct stat *out_st);