aboutsummaryrefslogtreecommitdiff
path: root/qemu-char.c
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2011-06-23 13:31:42 +0100
committerAnthony Liguori <aliguori@us.ibm.com>2011-07-23 11:19:02 -0500
commit13661089810d3e59931f3e80d7cb541b99af7071 (patch)
tree56f507cd78ea65ca7cb8e500d7b9ce57e54f7981 /qemu-char.c
parent7e7e2ebc942da8285931ceabf12823e165dced8b (diff)
Introduce a 'client_add' monitor command accepting an open FD
Allow client connections for VNC and socket based character devices to be passed in over the monitor using SCM_RIGHTS. One intended usage scenario is to start QEMU with VNC on a UNIX domain socket. An unprivileged user which cannot access the UNIX domain socket, can then connect to QEMU's VNC server by passing an open FD to libvirt, which passes it onto QEMU. { "execute": "get_fd", "arguments": { "fdname": "myclient" } } { "return": {} } { "execute": "add_client", "arguments": { "protocol": "vnc", "fdname": "myclient", "skipauth": true } } { "return": {} } In this case 'protocol' can be 'vnc' or 'spice', or the name of a character device (eg from -chardev id=XXXX) The 'skipauth' parameter can be used to skip any configured VNC authentication scheme, which is useful if the mgmt layer talking to the monitor has already authenticated the client in another way. * console.h: Define 'vnc_display_add_client' method * monitor.c: Implement 'client_add' command * qemu-char.c, qemu-char.h: Add 'qemu_char_add_client' method * qerror.c, qerror.h: Add QERR_ADD_CLIENT_FAILED * qmp-commands.hx: Declare 'client_add' command * ui/vnc.c: Implement 'vnc_display_add_client' method Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'qemu-char.c')
-rw-r--r--qemu-char.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/qemu-char.c b/qemu-char.c
index 926987b98a..dcf706592b 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -168,6 +168,11 @@ int qemu_chr_get_msgfd(CharDriverState *s)
return s->get_msgfd ? s->get_msgfd(s) : -1;
}
+int qemu_chr_add_client(CharDriverState *s, int fd)
+{
+ return s->chr_add_client ? s->chr_add_client(s, fd) : -1;
+}
+
void qemu_chr_accept_input(CharDriverState *s)
{
if (s->chr_accept_input)
@@ -2146,6 +2151,22 @@ static void socket_set_nodelay(int fd)
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
}
+static int tcp_chr_add_client(CharDriverState *chr, int fd)
+{
+ TCPCharDriver *s = chr->opaque;
+ if (s->fd != -1)
+ return -1;
+
+ socket_set_nonblock(fd);
+ if (s->do_nodelay)
+ socket_set_nodelay(fd);
+ s->fd = fd;
+ qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
+ tcp_chr_connect(chr);
+
+ return 0;
+}
+
static void tcp_chr_accept(void *opaque)
{
CharDriverState *chr = opaque;
@@ -2178,12 +2199,8 @@ static void tcp_chr_accept(void *opaque)
break;
}
}
- socket_set_nonblock(fd);
- if (s->do_nodelay)
- socket_set_nodelay(fd);
- s->fd = fd;
- qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
- tcp_chr_connect(chr);
+ if (tcp_chr_add_client(chr, fd) < 0)
+ close(fd);
}
static void tcp_chr_close(CharDriverState *chr)
@@ -2256,6 +2273,7 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
chr->chr_write = tcp_chr_write;
chr->chr_close = tcp_chr_close;
chr->get_msgfd = tcp_get_msgfd;
+ chr->chr_add_client = tcp_chr_add_client;
if (is_listen) {
s->listen_fd = fd;