From: "Daniel P. Berrange" <berrange(a)redhat.com>
Add APIs to the virNetSocket object, to allow file descriptors
to be sent/received over UNIX domain socket connections
* src/rpc/virnetsocket.c, src/rpc/virnetsocket.h,
src/libvirt_private.syms: Add APIs for FD send/recv
---
examples/systemtap/rpc-monitor.stp | 10 ++++++
src/libvirt_private.syms | 4 ++
src/probes.d | 2 +
src/rpc/virnetsocket.c | 62 ++++++++++++++++++++++++++++++++++++
src/rpc/virnetsocket.h | 5 +++
5 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/examples/systemtap/rpc-monitor.stp b/examples/systemtap/rpc-monitor.stp
index f246571..69d7593 100755
--- a/examples/systemtap/rpc-monitor.stp
+++ b/examples/systemtap/rpc-monitor.stp
@@ -155,3 +155,13 @@ probe libvirt.rpc.server_client_free {
delete serverSocks[pid(), client];
}
}
+
+
+probe libvirt.rpc.socket_send_fd {
+ print_ts(sprintf("= %-16p send fd=%d", sock, fd));
+}
+
+
+probe libvirt.rpc.socket_recv_fd {
+ print_ts(sprintf("= %-16p recv fd=%d", sock, fd));
+}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a81966d..6a42d1b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1252,9 +1252,13 @@ virNetServerProgramSendStreamError;
virNetSocketDupFD;
virNetSocketFree;
virNetSocketGetFD;
+virNetSocketHasPassFD;
+virNetSocketIsLocal;
virNetSocketListen;
virNetSocketNewConnectTCP;
virNetSocketNewListenUNIX;
+virNetSocketRecvFD;
+virNetSocketSendFD;
# virnettlscontext.h
diff --git a/src/probes.d b/src/probes.d
index 6d95c84..2f5d059 100644
--- a/src/probes.d
+++ b/src/probes.d
@@ -19,6 +19,8 @@ provider libvirt {
# file: src/rpc/virnetsocket.c
# prefix: rpc
probe rpc_socket_new(void *sock, int refs, int fd, int errfd, int pid, const char
*localAddr, const char *remoteAddr);
+ probe rpc_socket_send_fd(void *sock, int fd);
+ probe rpc_socket_recv_fd(void *sock, int fd);
probe rpc_socket_ref(void *sock, int refs);
probe rpc_socket_free(void *sock, int refs);
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index e4eff49..ab88e19 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -43,6 +43,8 @@
#include "event.h"
#include "threads.h"
+#include "passfd.h"
+
#define VIR_FROM_THIS VIR_FROM_RPC
#define virNetError(code, ...) \
@@ -791,6 +793,17 @@ bool virNetSocketIsLocal(virNetSocketPtr sock)
}
+bool virNetSocketHasPassFD(virNetSocketPtr sock)
+{
+ bool hasPassFD = false;
+ virMutexLock(&sock->lock);
+ if (sock->localAddr.data.sa.sa_family == AF_UNIX)
+ hasPassFD = true;
+ virMutexUnlock(&sock->lock);
+ return hasPassFD;
+}
+
+
int virNetSocketGetPort(virNetSocketPtr sock)
{
int port;
@@ -1128,6 +1141,55 @@ ssize_t virNetSocketWrite(virNetSocketPtr sock, const char *buf,
size_t len)
}
+int virNetSocketSendFD(virNetSocketPtr sock, int fd)
+{
+ int ret = -1;
+ if (!virNetSocketHasPassFD(sock)) {
+ virNetError(VIR_ERR_INTERNAL_ERROR,
+ _("Sending file descriptors is not supported on this
socket"));
+ return -1;
+ }
+ virMutexLock(&sock->lock);
+ PROBE(RPC_SOCKET_SEND_FD,
+ "sock=%p fd=%d", sock, fd);
+ if (sendfd(sock->fd, fd) < 0) {
+ virReportSystemError(errno,
+ _("Failed to send file descriptor %d"),
+ fd);
+ goto cleanup;
+ }
+ ret = 0;
+
+cleanup:
+ virMutexUnlock(&sock->lock);
+ return ret;
+}
+
+
+int virNetSocketRecvFD(virNetSocketPtr sock)
+{
+ int ret = -1;
+ if (!virNetSocketHasPassFD(sock)) {
+ virNetError(VIR_ERR_INTERNAL_ERROR,
+ _("Receiving file descriptors is not supported on this
socket"));
+ return -1;
+ }
+ virMutexLock(&sock->lock);
+
+ if ((ret = recvfd(sock->fd, O_CLOEXEC)) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Failed to recv file descriptor"));
+ goto cleanup;
+ }
+ PROBE(RPC_SOCKET_RECV_FD,
+ "sock=%p fd=%d", sock, ret);
+
+cleanup:
+ virMutexUnlock(&sock->lock);
+ return ret;
+}
+
+
int virNetSocketListen(virNetSocketPtr sock, int backlog)
{
virMutexLock(&sock->lock);
diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h
index 9c4f112..13cbb14 100644
--- a/src/rpc/virnetsocket.h
+++ b/src/rpc/virnetsocket.h
@@ -82,6 +82,8 @@ int virNetSocketDupFD(virNetSocketPtr sock, bool cloexec);
bool virNetSocketIsLocal(virNetSocketPtr sock);
+bool virNetSocketHasPassFD(virNetSocketPtr sock);
+
int virNetSocketGetPort(virNetSocketPtr sock);
int virNetSocketGetLocalIdentity(virNetSocketPtr sock,
@@ -94,6 +96,9 @@ int virNetSocketSetBlocking(virNetSocketPtr sock,
ssize_t virNetSocketRead(virNetSocketPtr sock, char *buf, size_t len);
ssize_t virNetSocketWrite(virNetSocketPtr sock, const char *buf, size_t len);
+int virNetSocketSendFD(virNetSocketPtr sock, int fd);
+int virNetSocketRecvFD(virNetSocketPtr sock);
+
void virNetSocketSetTLSSession(virNetSocketPtr sock,
virNetTLSSessionPtr sess);
# ifdef HAVE_SASL
--
1.7.6.4