}
+bool virNetClientHasPassFD(virNetClientPtr client)
+{
+ bool hasPassFD;
+ virNetClientLock(client);
+ hasPassFD = virNetSocketHasPassFD(client->sock);
+ virNetClientUnlock(client);
+ return hasPassFD;
+}
+
+
void virNetClientFree(virNetClientPtr client)
{
int i;
static int
virNetClientCallDispatch(virNetClientPtr client)
{
+ size_t i;
if (virNetMessageDecodeHeader(&client->msg) < 0)
return -1;
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);
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;
#include <config.h>
+#include <unistd.h>
+
#include "virnetclientprogram.h"
#include "virnetclient.h"
#include "virnetprotocol.h"
#include "memory.h"
#include "virterror_internal.h"
#include "logging.h"
+#include "util.h"
+#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_RPC
#define virNetError(code, ...) \
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 (infds)
+ *infds = NULL;
+ if (ninfds)
+ *ninfds = 0;
if (!(msg = virNetMessageNew(false)))
return -1;
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++)
+ msg->fds[i] = -1;
+ 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 (virSetInherit(msg->fds[i], false) < 0) {
+ virReportSystemError(errno,
+ _("Cannot set close-on-exec %d"),
+ msg->fds[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;
* 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;
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++)
+ *infds[i] = -1;
+ 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 (virSetInherit(*infds[i], false) < 0) {
+ virReportSystemError(errno,
+ _("Cannot set close-on-exec %d"),
+ *infds[i]);
+ goto error;
+ }
+ }
+
+ }
if (virNetMessageDecodePayload(msg, ret_filter, ret) < 0)
goto error;
break;
error:
virNetMessageFree(msg);
+ if (infds && ninfds) {
+ for (i = 0 ; i < *ninfds ; i++)
+ VIR_FORCE_CLOSE(*infds[i]);
+ }
return -1;
}