From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> Extend the RPC client code to allow file descriptors to be sent to the server with calls, and received back with replies. * src/remote/remote_driver.c: Stub extra args * src/libvirt_private.syms, src/rpc/virnetclient.c, src/rpc/virnetclient.h, src/rpc/virnetclientprogram.c, src/rpc/virnetclientprogram.h: Extend APIs to allow FD passing --- src/libvirt_private.syms | 4 +++ src/remote/remote_driver.c | 1 + src/rpc/virnetclient.c | 25 +++++++++++++++++++++++ src/rpc/virnetclient.h | 2 + src/rpc/virnetclientprogram.c | 44 +++++++++++++++++++++++++++++++++++++++- src/rpc/virnetclientprogram.h | 4 +++ 6 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f798c4a..fd107e7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1174,6 +1174,10 @@ virFileFclose; virFileFdopen; +# virnetclient.h +virNetClientHasPassFD; + + # virnetmessage.h virNetMessageClear; virNetMessageEncodeHeader; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 1dea327..fb16994 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -4116,6 +4116,7 @@ call (virConnectPtr conn ATTRIBUTE_UNUSED, client, counter, proc_nr, + 0, NULL, NULL, NULL, args_filter, args, ret_filter, ret); remoteDriverLock(priv); diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 085dc8d..e3ba157 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -258,6 +258,16 @@ int virNetClientDupFD(virNetClientPtr client, bool cloexec) } +bool virNetClientHasPassFD(virNetClientPtr client) +{ + int hasPassFD; + virNetClientLock(client); + hasPassFD = virNetSocketHasPassFD(client->sock); + virNetClientUnlock(client); + return hasPassFD; +} + + void virNetClientFree(virNetClientPtr client) { int i; @@ -684,6 +694,7 @@ static int virNetClientCallDispatchStream(virNetClientPtr client) static int virNetClientCallDispatch(virNetClientPtr client) { + size_t i; if (virNetMessageDecodeHeader(&client->msg) < 0) return -1; @@ -697,6 +708,15 @@ virNetClientCallDispatch(virNetClientPtr client) case VIR_NET_REPLY: /* Normal RPC replies */ return virNetClientCallDispatchReply(client); + case VIR_NET_REPLY_WITH_FDS: /* Normal RPC replies with FDs */ + if (virNetMessageDecodeNumFDs(&client->msg) < 0) + return -1; + for (i = 0 ; i < client->msg.nfds ; i++) { + if ((client->msg.fds[i] = virNetSocketRecvFD(client->sock)) < 0) + return -1; + } + return virNetClientCallDispatchReply(client); + case VIR_NET_MESSAGE: /* Async notifications */ return virNetClientCallDispatchMessage(client); @@ -728,6 +748,11 @@ virNetClientIOWriteMessage(virNetClientPtr client, thecall->msg->bufferOffset += ret; if (thecall->msg->bufferOffset == thecall->msg->bufferLength) { + size_t i; + for (i = 0 ; i < thecall->msg->nfds ; i++) { + if (virNetSocketSendFD(client->sock, thecall->msg->fds[i]) < 0) + return -1; + } thecall->msg->bufferOffset = thecall->msg->bufferLength = 0; if (thecall->expectReply) thecall->mode = VIR_NET_CLIENT_MODE_WAIT_RX; diff --git a/src/rpc/virnetclient.h b/src/rpc/virnetclient.h index 1fabcfd..fb679e8 100644 --- a/src/rpc/virnetclient.h +++ b/src/rpc/virnetclient.h @@ -56,6 +56,8 @@ void virNetClientRef(virNetClientPtr client); int virNetClientGetFD(virNetClientPtr client); int virNetClientDupFD(virNetClientPtr client, bool cloexec); +bool virNetClientHasPassFD(virNetClientPtr client); + int virNetClientAddProgram(virNetClientPtr client, virNetClientProgramPtr prog); diff --git a/src/rpc/virnetclientprogram.c b/src/rpc/virnetclientprogram.c index 33fa507..4ff6cf3 100644 --- a/src/rpc/virnetclientprogram.c +++ b/src/rpc/virnetclientprogram.c @@ -22,6 +22,8 @@ #include <config.h> +#include <unistd.h> + #include "virnetclientprogram.h" #include "virnetclient.h" #include "virnetprotocol.h" @@ -267,10 +269,15 @@ int virNetClientProgramCall(virNetClientProgramPtr prog, virNetClientPtr client, unsigned serial, int proc, + size_t noutfds, + int *outfds, + size_t *ninfds, + int **infds, xdrproc_t args_filter, void *args, xdrproc_t ret_filter, void *ret) { virNetMessagePtr msg; + size_t i; if (!(msg = virNetMessageNew(false))) return -1; @@ -278,13 +285,30 @@ int virNetClientProgramCall(virNetClientProgramPtr prog, msg->header.prog = prog->program; msg->header.vers = prog->version; msg->header.status = VIR_NET_OK; - msg->header.type = VIR_NET_CALL; + msg->header.type = noutfds ? VIR_NET_CALL_WITH_FDS : VIR_NET_CALL; msg->header.serial = serial; msg->header.proc = proc; + msg->nfds = noutfds; + if (VIR_ALLOC_N(msg->fds, msg->nfds) < 0) { + virReportOOMError(); + goto error; + } + for (i = 0 ; i < msg->nfds ; i++) { + if ((msg->fds[i] = dup(outfds[i])) < 0) { + virReportSystemError(errno, + _("Cannot duplicate FD %d"), + outfds[i]); + goto error; + } + } if (virNetMessageEncodeHeader(msg) < 0) goto error; + if (msg->nfds && + virNetMessageEncodeNumFDs(msg) < 0) + goto error; + if (virNetMessageEncodePayload(msg, args_filter, args) < 0) goto error; @@ -295,7 +319,8 @@ int virNetClientProgramCall(virNetClientProgramPtr prog, * virNetClientSend should have validated the reply, * but it doesn't hurt to check again. */ - if (msg->header.type != VIR_NET_REPLY) { + if (msg->header.type != VIR_NET_REPLY && + msg->header.type != VIR_NET_REPLY_WITH_FDS) { virNetError(VIR_ERR_INTERNAL_ERROR, _("Unexpected message type %d"), msg->header.type); goto error; @@ -315,6 +340,21 @@ int virNetClientProgramCall(virNetClientProgramPtr prog, switch (msg->header.status) { case VIR_NET_OK: + if (infds && ninfds) { + *ninfds = msg->nfds; + if (VIR_ALLOC_N(*infds, *ninfds) < 0) { + virReportOOMError(); + goto error; + } + for (i = 0 ; i < *ninfds ; i++) { + if ((*infds[i] = dup(msg->fds[i])) < 0) { + virReportSystemError(errno, + _("Cannot duplicate FD %d"), + msg->fds[i]); + goto error; + } + } + } if (virNetMessageDecodePayload(msg, ret_filter, ret) < 0) goto error; break; diff --git a/src/rpc/virnetclientprogram.h b/src/rpc/virnetclientprogram.h index 82ae2c6..14a4c96 100644 --- a/src/rpc/virnetclientprogram.h +++ b/src/rpc/virnetclientprogram.h @@ -77,6 +77,10 @@ int virNetClientProgramCall(virNetClientProgramPtr prog, virNetClientPtr client, unsigned serial, int proc, + size_t noutfds, + int *outfds, + size_t *ninfds, + int **infds, xdrproc_t args_filter, void *args, xdrproc_t ret_filter, void *ret); -- 1.7.6.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list