diff --git a/daemon/remote.c b/daemon/remote.c index ea1678967912c51b3ce46588fcaa8417b7839626..27d1aa8037c5f1b6c02e9fd2c549a5678a24b5f3 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -4398,6 +4398,50 @@ remoteDispatchDomainOpenGraphics(virNetServerPtr server ATTRIBUTE_UNUSED, return rv; } +static int +remoteDispatchDomainOpenGraphicsFd(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg, + virNetMessageErrorPtr rerr, + remote_domain_open_graphics_fd_args *args) +{ + virDomainPtr dom = NULL; + int rv = -1; + int fd = -1; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) + goto cleanup; + + if (virDomainOpenGraphicsFD(dom, + args->idx, + &fd, + args->flags) < 0) + goto cleanup; + + if (virNetMessageAddFD(msg, fd) < 0) + goto cleanup; + + /* return 1 here to let virNetServerProgramDispatchCall know + * we are passing a FD */ + rv = 1; + + cleanup: + VIR_FORCE_CLOSE(fd); + if (rv < 0) { + virNetMessageSaveError(rerr); + } + + if (dom) + virDomainFree(dom); + return rv; +} static int remoteDispatchDomainGetInterfaceParameters(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client ATTRIBUTE_UNUSED, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 9a1d78fc4f10a4a768d6fdbff5c7a5a4a535500c..e01216a86132248fc96eae00e5fd4754f2007b27 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -6445,6 +6445,48 @@ remoteDomainOpenGraphics(virDomainPtr dom, } +static int +remoteDomainOpenGraphicsFD(virDomainPtr dom, + unsigned int idx, + int *fd, + unsigned int flags) +{ + int rv = -1; + remote_domain_open_graphics_args args; + struct private_data *priv = dom->conn->privateData; + int *fdout = NULL; + size_t fdoutlen = 0; + + remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, dom); + args.idx = idx; + args.flags = flags; + + if (callFull(dom->conn, priv, 0, + NULL, 0, + &fdout, &fdoutlen, + REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD, + (xdrproc_t) xdr_remote_domain_open_graphics_fd_args, (char *) &args, + (xdrproc_t) xdr_void, NULL) == -1) + goto done; + + if (fdoutlen != 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("no file descriptor received")); + goto done; + } + *fd = fdout[0]; + + rv = 0; + + done: + remoteDriverUnlock(priv); + + return rv; +} + + static int remoteConnectSetKeepAlive(virConnectPtr conn, int interval, unsigned int count) { @@ -7963,6 +8005,7 @@ static virDriver remote_driver = { .domainOpenConsole = remoteDomainOpenConsole, /* 0.8.6 */ .domainOpenChannel = remoteDomainOpenChannel, /* 1.0.2 */ .domainOpenGraphics = remoteDomainOpenGraphics, /* 0.9.7 */ + .domainOpenGraphicsFD = remoteDomainOpenGraphicsFD, /* 1.2.8 */ .domainInjectNMI = remoteDomainInjectNMI, /* 0.9.2 */ .domainMigrateBegin3 = remoteDomainMigrateBegin3, /* 0.9.2 */ .domainMigratePrepare3 = remoteDomainMigratePrepare3, /* 0.9.2 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 5c316fb5769c1279743aba9323876b8e16e506b8..6dc2d292507ca77b3a355564623336f4737c9479 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2733,6 +2733,12 @@ struct remote_domain_open_graphics_args { unsigned int flags; }; +struct remote_domain_open_graphics_fd_args { + remote_nonnull_domain dom; + unsigned int idx; + unsigned int flags; +}; + struct remote_node_suspend_for_duration_args { unsigned int target; unsigned hyper duration; @@ -5420,5 +5426,12 @@ enum remote_procedure { * @generate: both * @acl: connect:write */ - REMOTE_PROC_CONNECT_GET_DOMAIN_CAPABILITIES = 342 + REMOTE_PROC_CONNECT_GET_DOMAIN_CAPABILITIES = 342, + + /** + * @generate: none + * @acl: domain:open_graphics + */ + REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343 + }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 9bf09b84179b6243ffc7db4c598ff823e38283f3..38bf0b8582a434c4d01dcea36ee7aefacf844986 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2153,6 +2153,11 @@ struct remote_domain_open_graphics_args { u_int idx; u_int flags; }; +struct remote_domain_open_graphics_fd_args { + remote_nonnull_domain dom; + u_int idx; + u_int flags; +}; struct remote_node_suspend_for_duration_args { u_int target; uint64_t duration; @@ -2862,4 +2867,5 @@ enum remote_procedure { REMOTE_PROC_NODE_GET_FREE_PAGES = 340, REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 341, REMOTE_PROC_CONNECT_GET_DOMAIN_CAPABILITIES = 342, + REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343, }; diff --git a/src/rpc/virnetmessage.c b/src/rpc/virnetmessage.c index 19b2d6ce21020f60d8137507ec0941ada7a6e089..5c57128c13ab1e3944c35e180ef9a430f9d78b09 100644 --- a/src/rpc/virnetmessage.c +++ b/src/rpc/virnetmessage.c @@ -564,3 +564,29 @@ int virNetMessageDupFD(virNetMessagePtr msg, } return fd; } + +int virNetMessageAddFD(virNetMessagePtr msg, + int fd) +{ + int newfd = -1; + + if ((newfd = dup(fd)) < 0) { + virReportSystemError(errno, + _("Unable to duplicate FD %d"), + fd); + goto error; + } + + if (virSetInherit(newfd, false) < 0) { + virReportSystemError(errno, + _("Cannot set close-on-exec %d"), + newfd); + goto error; + } + if (VIR_APPEND_ELEMENT(msg->fds, msg->nfds, newfd) < 0) + goto error; + return 0; + error: + VIR_FORCE_CLOSE(newfd); + return -1; +} diff --git a/src/rpc/virnetmessage.h b/src/rpc/virnetmessage.h index c94dddc2591c820afc7d79ded67da1a14f46d926..89a2ebf71692110cc9fbf39e2085e4e75fabb4ff 100644 --- a/src/rpc/virnetmessage.h +++ b/src/rpc/virnetmessage.h @@ -96,4 +96,7 @@ void virNetMessageSaveError(virNetMessageErrorPtr rerr) int virNetMessageDupFD(virNetMessagePtr msg, size_t slot); +int virNetMessageAddFD(virNetMessagePtr msg, + int fd); + #endif /* __VIR_NET_MESSAGE_H__ */