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 <prapal(a)linux.microsoft.com>
---
po/POTFILES | 1 +
src/libvirt_private.syms | 2 +
src/util/virsocket.c | 116 +++++++++++++++++++++++++++++++++++++++
src/util/virsocket.h | 3 +
4 files changed, 122 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 80d43ed15d..2c9b2635cd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3371,8 +3371,10 @@ virSecureEraseString;
# util/virsocket.h
+virSocketRecv;
virSocketRecvFD;
virSocketSendFD;
+virSocketSendMsgWithFDs;
# util/virsocketaddr.h
diff --git a/src/util/virsocket.c b/src/util/virsocket.c
index cd6f7ecd1b..8019fd1199 100644
--- a/src/util/virsocket.c
+++ b/src/util/virsocket.c
@@ -19,11 +19,18 @@
#include <config.h>
+#include "virerror.h"
#include "virsocket.h"
#include "virutil.h"
#include "virfile.h"
+#include "virlog.h"
#include <fcntl.h>
+#include <poll.h>
+
+#define PKT_TIMEOUT_MS 500 /* ms */
+
+#define VIR_FROM_THIS VIR_FROM_NONE
#ifdef WIN32
@@ -482,6 +489,108 @@ 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)
+{
+ struct msghdr msg;
+ struct iovec iov[1]; /* Send a single payload, so set vector len to 1 */
+ int ret;
+ char control[CMSG_SPACE(sizeof(int)*fds_len)];
+ struct cmsghdr *cmsg;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(control, 0, sizeof(control));
+
+ 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 = sizeof(control);
+
+ 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;
+}
+
+/**
+ * virSocketRecv:
+ * @sock: socket to poll and receive response on
+ *
+ * This function polls @sock for response
+ * Returns received response or NULL on error.
+ */
+char *
+virSocketRecv(int sock)
+{
+ struct pollfd pfds[1];
+ char *buf = NULL;
+ size_t buf_len = 1024;
+ int ret;
+
+ buf = g_new0(char, buf_len);
+
+ pfds[0].fd = sock;
+ pfds[0].events = POLLIN;
+
+ do {
+ ret = poll(pfds, G_N_ELEMENTS(pfds), PKT_TIMEOUT_MS);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret <= 0) {
+ if (ret < 0) {
+ virReportSystemError(errno, _("Poll on sock %1$d failed"), sock);
+ } else if (ret == 0) {
+ virReportSystemError(errno, _("Poll on sock %1$d timed out"),
sock);
+ }
+ return NULL;
+ }
+
+ do {
+ ret = recv(sock, buf, buf_len-1, 0);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0) {
+ virReportSystemError(errno, _("recv on sock %1$d failed"), sock);
+ return NULL;
+ }
+
+ return g_steal_pointer(&buf);
+}
+
#else /* WIN32 */
int
virSocketSendFD(int sock G_GNUC_UNUSED, int fd G_GNUC_UNUSED)
@@ -496,4 +605,11 @@ virSocketRecvFD(int sock G_GNUC_UNUSED, int fdflags G_GNUC_UNUSED)
errno = ENOSYS;
return -1;
}
+
+int
+virSocketSendMsgWithFDs(int sock, const char *payload, int *fds, size_t fds_len)
+{
+ errno = ENOSYS;
+ return -1;
+}
#endif /* WIN32 */
diff --git a/src/util/virsocket.h b/src/util/virsocket.h
index 419da8b3ae..00fbf52603 100644
--- a/src/util/virsocket.h
+++ b/src/util/virsocket.h
@@ -22,6 +22,9 @@
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);
+char * virSocketRecv(int sock);
#ifdef WIN32
--
2.43.0