From e7daa49a153ce79ef19411ae93f2840d7b7f7902 Mon Sep 17 00:00:00 2001 From: Praveen K Paladugu Date: Tue, 16 Jan 2024 15:25:41 -0600 Subject: [PATCH] util: Add util methods required by ch networking virSocketSendMsgWithFDs method send fds along with payload using SCM_RIGHTS. virSocketRecv method polls, receives and sends the response to callers. These methods are required to add network suppport in ch driver. Signed-off-by: Praveen K Paladugu Signed-off-by: Michal Privoznik Reviewed-by: Michal Privoznik --- po/POTFILES | 1 + src/libvirt_private.syms | 1 + src/util/virsocket.c | 76 ++++++++++++++++++++++++++++++++++++++++ src/util/virsocket.h | 2 ++ 4 files changed, 80 insertions(+) diff --git a/po/POTFILES b/po/POTFILES index 023c041f61..b594a8dd39 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -326,6 +326,7 @@ src/util/virscsi.c src/util/virscsihost.c src/util/virscsivhost.c src/util/virsecret.c +src/util/virsocket.c src/util/virsocketaddr.c src/util/virstoragefile.c src/util/virstring.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1a7d80ddf4..c398371734 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3372,6 +3372,7 @@ virSecureEraseString; # util/virsocket.h virSocketRecvFD; virSocketSendFD; +virSocketSendMsgWithFDs; # util/virsocketaddr.h diff --git a/src/util/virsocket.c b/src/util/virsocket.c index cd6f7ecd1b..3b274a4eec 100644 --- a/src/util/virsocket.c +++ b/src/util/virsocket.c @@ -19,11 +19,18 @@ #include +#include "virerror.h" #include "virsocket.h" #include "virutil.h" #include "virfile.h" +#include "virlog.h" #include +#include + +#define PKT_TIMEOUT_MS 500 /* ms */ + +#define VIR_FROM_THIS VIR_FROM_NONE #ifdef WIN32 @@ -482,6 +489,64 @@ virSocketRecvFD(int sock, int fdflags) return fd; } + + +/** + * virSocketSendMsgWithFDs: + * @sock: socket to send payload and fds to + * @payload: payload to send + * @fds: array of fds to send + * @fds_len: len of fds array + + * Send @fds along with @payload to @sock using SCM_RIGHTS. + * Return number of bytes sent on success. + * On error, set errno and return -1. + */ +int +virSocketSendMsgWithFDs(int sock, const char *payload, int *fds, size_t fds_len) +{ + g_autofree char *control = NULL; + const size_t control_size = CMSG_SPACE(sizeof(int) * fds_len); + struct cmsghdr *cmsg; + struct msghdr msg = { 0 }; + struct iovec iov[1]; /* Send a single payload, so set vector len to 1 */ + int ret; + + control = g_new0(char, control_size); + + iov[0].iov_base = (void *) payload; + iov[0].iov_len = strlen(payload); + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + msg.msg_control = control; + msg.msg_controllen = control_size; + + cmsg = CMSG_FIRSTHDR(&msg); + /* check to eliminate "potential null pointer dereference" errors during build */ + if (!cmsg) { + virReportSystemError(EFAULT, "%s", _("Couldn't fit control msg header in msg")); + return -1; + } + + cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds_len); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * fds_len); + + do { + ret = sendmsg(sock, &msg, 0); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + virReportSystemError(errno, "%s", _("sendmsg failed")); + return -1; + } + + return ret; +} + #else /* WIN32 */ int virSocketSendFD(int sock G_GNUC_UNUSED, int fd G_GNUC_UNUSED) @@ -496,4 +561,15 @@ virSocketRecvFD(int sock G_GNUC_UNUSED, int fdflags G_GNUC_UNUSED) errno = ENOSYS; return -1; } + +int +virSocketSendMsgWithFDs(int sock G_GNUC_UNUSED, + const char *payload G_GNUC_UNUSED, + int *fds G_GNUC_UNUSED, + size_t fds_len G_GNUC_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("FD passing is not supported on this platform")); + return -1; +} #endif /* WIN32 */ diff --git a/src/util/virsocket.h b/src/util/virsocket.h index 419da8b3ae..31a31c2378 100644 --- a/src/util/virsocket.h +++ b/src/util/virsocket.h @@ -22,6 +22,8 @@ int virSocketSendFD(int sock, int fd); int virSocketRecvFD(int sock, int fdflags); +int virSocketSendMsgWithFDs(int sock, const char *payload, int *fds, + size_t fd_len); #ifdef WIN32