[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/3] Add SCM_RIGHTS support to unix socket character
From: |
Mark McLoughlin |
Subject: |
[Qemu-devel] [PATCH 2/3] Add SCM_RIGHTS support to unix socket character devices |
Date: |
Mon, 06 Jul 2009 18:31:35 +0100 |
If a file descriptor is passed via a message with SCM_RIGHTS ancillary
data on a unix socket, store the file descriptor for use in the
chr_read() handler. Close the file descriptor if it was not used.
The qemu_chr_get_msgfd() and monitor_get_msgfd() APIs provide access
to any passed descriptor.
Signed-off-by: Mark McLoughlin <address@hidden>
---
monitor.c | 5 +++++
monitor.h | 1 +
qemu-char.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-char.h | 2 ++
4 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/monitor.c b/monitor.c
index bad79fe..f61f43d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2981,6 +2981,11 @@ static void monitor_read(void *opaque, const uint8_t
*buf, int size)
cur_mon = old_mon;
}
+int monitor_get_msgfd(Monitor *mon)
+{
+ return qemu_chr_get_msgfd(mon->chr);
+}
+
static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
{
monitor_suspend(mon);
diff --git a/monitor.h b/monitor.h
index 13e8cc7..af97a86 100644
--- a/monitor.h
+++ b/monitor.h
@@ -19,6 +19,7 @@ void monitor_resume(Monitor *mon);
void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
BlockDriverCompletionFunc *completion_cb,
void *opaque);
+int monitor_get_msgfd(Monitor *mon);
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap);
void monitor_printf(Monitor *mon, const char *fmt, ...)
diff --git a/qemu-char.c b/qemu-char.c
index e0d7220..f06a614 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int
len)
s->chr_read(s->handler_opaque, buf, len);
}
+int qemu_chr_get_msgfd(CharDriverState *s)
+{
+ return s->get_msgfd ? s->get_msgfd(s) : -1;
+}
+
void qemu_chr_accept_input(CharDriverState *s)
{
if (s->chr_accept_input)
@@ -1832,6 +1837,7 @@ typedef struct {
int do_telnetopt;
int do_nodelay;
int is_unix;
+ int msgfd;
} TCPCharDriver;
static void tcp_chr_accept(void *opaque);
@@ -1907,12 +1913,46 @@ static void tcp_chr_process_IAC_bytes(CharDriverState
*chr,
*size = j;
}
+static int tcp_get_msgfd(CharDriverState *chr)
+{
+ TCPCharDriver *s = chr->opaque;
+
+ return s->msgfd;
+}
+
+static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
+{
+ TCPCharDriver *s = chr->opaque;
+ struct cmsghdr *cmsg;
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ int fd;
+
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+ cmsg->cmsg_level != SOL_SOCKET ||
+ cmsg->cmsg_type != SCM_RIGHTS)
+ continue;
+
+ fd = *((int *)CMSG_DATA(cmsg));
+ if (fd < 0)
+ continue;
+
+ if (s->msgfd != -1)
+ close(s->msgfd);
+ s->msgfd = fd;
+ }
+}
+
static void tcp_chr_read(void *opaque)
{
CharDriverState *chr = opaque;
TCPCharDriver *s = chr->opaque;
struct msghdr msg = { 0, };
struct iovec iov[1];
+ union {
+ struct cmsghdr cmsg;
+ char control[CMSG_SPACE(sizeof(int))];
+ } msg_control;
uint8_t buf[1024];
int len, size;
@@ -1928,6 +1968,8 @@ static void tcp_chr_read(void *opaque)
msg.msg_iov = iov;
msg.msg_iovlen = 1;
+ msg.msg_control = &msg_control;
+ msg.msg_controllen = sizeof(msg_control);
size = recvmsg(s->fd, &msg, 0);
if (size == 0) {
@@ -1940,10 +1982,16 @@ static void tcp_chr_read(void *opaque)
closesocket(s->fd);
s->fd = -1;
} else if (size > 0) {
+ if (s->is_unix)
+ unix_process_msgfd(chr, &msg);
if (s->do_telnetopt)
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
if (size > 0)
qemu_chr_read(chr, buf, size);
+ if (s->msgfd != -1) {
+ close(s->msgfd);
+ s->msgfd = -1;
+ }
}
}
@@ -2105,12 +2153,14 @@ static CharDriverState *qemu_chr_open_tcp(const char
*host_str,
s->connected = 0;
s->fd = -1;
s->listen_fd = -1;
+ s->msgfd = -1;
s->is_unix = is_unix;
s->do_nodelay = do_nodelay && !is_unix;
chr->opaque = s;
chr->chr_write = tcp_chr_write;
chr->chr_close = tcp_chr_close;
+ chr->get_msgfd = tcp_get_msgfd;
if (is_listen) {
s->listen_fd = fd;
diff --git a/qemu-char.h b/qemu-char.h
index e1aa8db..77d4eda 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -51,6 +51,7 @@ struct CharDriverState {
int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
void (*chr_update_read_handler)(struct CharDriverState *s);
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
+ int (*get_msgfd)(struct CharDriverState *s);
IOEventHandler *chr_event;
IOCanRWHandler *chr_can_read;
IOReadHandler *chr_read;
@@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s);
void qemu_chr_initial_reset(void);
int qemu_chr_can_read(CharDriverState *s);
void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
+int qemu_chr_get_msgfd(CharDriverState *s);
void qemu_chr_accept_input(CharDriverState *s);
void qemu_chr_info(Monitor *mon);
--
1.6.2.5
- [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Mark McLoughlin, 2009/07/06
- [Qemu-devel] [PATCH 1/3] Make tcp_chr_read() use recvmsg(), Mark McLoughlin, 2009/07/06
- [Qemu-devel] [PATCH 2/3] Add SCM_RIGHTS support to unix socket character devices,
Mark McLoughlin <=
- Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Avi Kivity, 2009/07/07
- Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Mark McLoughlin, 2009/07/07
- Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Avi Kivity, 2009/07/07
- Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Mark McLoughlin, 2009/07/07
- Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Avi Kivity, 2009/07/07
- Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Daniel P. Berrange, 2009/07/07
- Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors, Mark McLoughlin, 2009/07/08
- [Qemu-devel] [PATCH 1/5] Make tcp_chr_read() use recvmsg(), Mark McLoughlin, 2009/07/08
- [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices, Mark McLoughlin, 2009/07/08