diff --git a/monitor/fds.c b/monitor/fds.c index 7daf1064e1..9ed4197358 100644 --- a/monitor/fds.c +++ b/monitor/fds.c @@ -61,11 +61,47 @@ struct MonFdset { static QemuMutex mon_fdsets_lock; static QLIST_HEAD(, MonFdset) mon_fdsets; +static bool monitor_add_fd(Monitor *mon, int fd, const char *fdname, Error **errp) +{ + mon_fd_t *monfd; + + if (qemu_isdigit(fdname[0])) { + close(fd); + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdname", + "a name not starting with a digit"); + return false; + } + + /* See close() call below. */ + qemu_mutex_lock(&mon->mon_lock); + QLIST_FOREACH(monfd, &mon->fds, next) { + int tmp_fd; + + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + tmp_fd = monfd->fd; + monfd->fd = fd; + qemu_mutex_unlock(&mon->mon_lock); + /* Make sure close() is outside critical section */ + close(tmp_fd); + return true; + } + + monfd = g_new0(mon_fd_t, 1); + monfd->name = g_strdup(fdname); + monfd->fd = fd; + + QLIST_INSERT_HEAD(&mon->fds, monfd, next); + qemu_mutex_unlock(&mon->mon_lock); + return true; +} + void qmp_getfd(const char *fdname, Error **errp) { Monitor *cur_mon = monitor_cur(); - mon_fd_t *monfd; - int fd, tmp_fd; + int fd; fd = qemu_chr_fe_get_msgfd(&cur_mon->chr); if (fd == -1) { @@ -73,34 +109,7 @@ void qmp_getfd(const char *fdname, Error **errp) return; } - if (qemu_isdigit(fdname[0])) { - close(fd); - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdname", - "a name not starting with a digit"); - return; - } - - /* See close() call below. */ - qemu_mutex_lock(&cur_mon->mon_lock); - QLIST_FOREACH(monfd, &cur_mon->fds, next) { - if (strcmp(monfd->name, fdname) != 0) { - continue; - } - - tmp_fd = monfd->fd; - monfd->fd = fd; - qemu_mutex_unlock(&cur_mon->mon_lock); - /* Make sure close() is outside critical section */ - close(tmp_fd); - return; - } - - monfd = g_new0(mon_fd_t, 1); - monfd->name = g_strdup(fdname); - monfd->fd = fd; - - QLIST_INSERT_HEAD(&cur_mon->fds, monfd, next); - qemu_mutex_unlock(&cur_mon->mon_lock); + monitor_add_fd(cur_mon, fd, fdname, errp); } void qmp_closefd(const char *fdname, Error **errp) @@ -214,6 +223,41 @@ error: return NULL; } +#ifdef WIN32 +void qmp_get_win32_socket(const char *infos, const char *fdname, Error **errp) +{ + g_autofree WSAPROTOCOL_INFOW *info = NULL; + gsize len; + SOCKET sk; + int fd; + + info = (void *)g_base64_decode(infos, &len); + if (len != sizeof(*info)) { + error_setg(errp, "Invalid WSAPROTOCOL_INFOW value"); + return; + } + + sk = WSASocketW(FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + info, 0, 0); + if (sk == INVALID_SOCKET) { + error_setg_win32(errp, WSAGetLastError(), "Couldn't import socket"); + return; + } + + fd = _open_osfhandle(sk, _O_BINARY); + if (fd < 0) { + error_setg_errno(errp, errno, "Failed to associate a FD with the SOCKET"); + closesocket(sk); + return; + } + + monitor_add_fd(monitor_cur(), fd, fdname, errp); +} +#endif + + void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp) { MonFdset *mon_fdset; diff --git a/qapi/misc.json b/qapi/misc.json index f0217cfba0..5ef6286af3 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -275,6 +275,37 @@ ## { 'command': 'getfd', 'data': {'fdname': 'str'} } +## +# @get-win32-socket: +# +# Add a socket that was duplicated to QEMU process with +# WSADuplicateSocketW() via WSASocket() & WSAPROTOCOL_INFOW structure +# and assign it a name (the SOCKET is associated with a CRT file +# descriptor) +# +# @info: the WSAPROTOCOL_INFOW structure (encoded in base64) +# +# @fdname: file descriptor name +# +# Returns: Nothing on success +# +# Since: 8.0 +# +# Notes: If @fdname already exists, the file descriptor assigned to +# it will be closed and replaced by the received file +# descriptor. +# +# The 'closefd' command can be used to explicitly close the +# file descriptor when it is no longer needed. +# +# Example: +# +# -> { "execute": "get-win32-socket", "arguments": { "info": "abcd123..", fdname": "skclient" } } +# <- { "return": {} } +# +## +{ 'command': 'get-win32-socket', 'data': {'info': 'str', 'fdname': 'str'}, 'if': 'CONFIG_WIN32' } + ## # @closefd: #