mirror of https://github.com/xemu-project/xemu.git
Add chardev API qemu_chr_fe_get_msgfds
This extends the existing qemu_chr_fe_get_msgfd by allowing to read a set of fds. The function for receiving the fds - unix_process_msgfd is extended to allocate the needed array size. Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
d39aac7aac
commit
c76bf6bb8f
|
@ -61,7 +61,7 @@ struct CharDriverState {
|
||||||
GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond);
|
GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond);
|
||||||
void (*chr_update_read_handler)(struct CharDriverState *s);
|
void (*chr_update_read_handler)(struct CharDriverState *s);
|
||||||
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
|
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
|
||||||
int (*get_msgfd)(struct CharDriverState *s);
|
int (*get_msgfds)(struct CharDriverState *s, int* fds, int num);
|
||||||
int (*set_msgfds)(struct CharDriverState *s, int *fds, int num);
|
int (*set_msgfds)(struct CharDriverState *s, int *fds, int num);
|
||||||
int (*chr_add_client)(struct CharDriverState *chr, int fd);
|
int (*chr_add_client)(struct CharDriverState *chr, int fd);
|
||||||
IOEventHandler *chr_event;
|
IOEventHandler *chr_event;
|
||||||
|
@ -229,6 +229,19 @@ int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg);
|
||||||
*/
|
*/
|
||||||
int qemu_chr_fe_get_msgfd(CharDriverState *s);
|
int qemu_chr_fe_get_msgfd(CharDriverState *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @qemu_chr_fe_get_msgfds:
|
||||||
|
*
|
||||||
|
* For backends capable of fd passing, return the number of file received
|
||||||
|
* descriptors and fills the fds array up to num elements
|
||||||
|
*
|
||||||
|
* Returns: -1 if fd passing isn't supported or there are no pending file
|
||||||
|
* descriptors. If file descriptors are returned, subsequent calls to
|
||||||
|
* this function will return -1 until a client sends a new set of file
|
||||||
|
* descriptors.
|
||||||
|
*/
|
||||||
|
int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int num);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @qemu_chr_fe_set_msgfds:
|
* @qemu_chr_fe_set_msgfds:
|
||||||
*
|
*
|
||||||
|
|
85
qemu-char.c
85
qemu-char.c
|
@ -204,7 +204,13 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len)
|
||||||
|
|
||||||
int qemu_chr_fe_get_msgfd(CharDriverState *s)
|
int qemu_chr_fe_get_msgfd(CharDriverState *s)
|
||||||
{
|
{
|
||||||
return s->get_msgfd ? s->get_msgfd(s) : -1;
|
int fd;
|
||||||
|
return (qemu_chr_fe_get_msgfds(s, &fd, 1) >= 0) ? fd : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int len)
|
||||||
|
{
|
||||||
|
return s->get_msgfds ? s->get_msgfds(s, fds, len) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_chr_fe_set_msgfds(CharDriverState *s, int *fds, int num)
|
int qemu_chr_fe_set_msgfds(CharDriverState *s, int *fds, int num)
|
||||||
|
@ -2337,7 +2343,8 @@ typedef struct {
|
||||||
int do_telnetopt;
|
int do_telnetopt;
|
||||||
int do_nodelay;
|
int do_nodelay;
|
||||||
int is_unix;
|
int is_unix;
|
||||||
int msgfd;
|
int *read_msgfds;
|
||||||
|
int read_msgfds_num;
|
||||||
int *write_msgfds;
|
int *write_msgfds;
|
||||||
int write_msgfds_num;
|
int write_msgfds_num;
|
||||||
} TCPCharDriver;
|
} TCPCharDriver;
|
||||||
|
@ -2469,12 +2476,20 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
|
||||||
*size = j;
|
*size = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcp_get_msgfd(CharDriverState *chr)
|
static int tcp_get_msgfds(CharDriverState *chr, int *fds, int num)
|
||||||
{
|
{
|
||||||
TCPCharDriver *s = chr->opaque;
|
TCPCharDriver *s = chr->opaque;
|
||||||
int fd = s->msgfd;
|
int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
|
||||||
s->msgfd = -1;
|
|
||||||
return fd;
|
if (to_copy) {
|
||||||
|
memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
|
||||||
|
|
||||||
|
g_free(s->read_msgfds);
|
||||||
|
s->read_msgfds = 0;
|
||||||
|
s->read_msgfds_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcp_set_msgfds(CharDriverState *chr, int *fds, int num)
|
static int tcp_set_msgfds(CharDriverState *chr, int *fds, int num)
|
||||||
|
@ -2503,26 +2518,46 @@ static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
|
|
||||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||||
int fd;
|
int fd_size, i;
|
||||||
|
|
||||||
if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
|
if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) ||
|
||||||
cmsg->cmsg_level != SOL_SOCKET ||
|
cmsg->cmsg_level != SOL_SOCKET ||
|
||||||
cmsg->cmsg_type != SCM_RIGHTS)
|
cmsg->cmsg_type != SCM_RIGHTS) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
fd = *((int *)CMSG_DATA(cmsg));
|
fd_size = cmsg->cmsg_len - CMSG_LEN(0);
|
||||||
if (fd < 0)
|
|
||||||
|
if (!fd_size) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
|
/* close and clean read_msgfds */
|
||||||
qemu_set_block(fd);
|
for (i = 0; i < s->read_msgfds_num; i++) {
|
||||||
|
close(s->read_msgfds[i]);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef MSG_CMSG_CLOEXEC
|
if (s->read_msgfds_num) {
|
||||||
qemu_set_cloexec(fd);
|
g_free(s->read_msgfds);
|
||||||
#endif
|
}
|
||||||
if (s->msgfd != -1)
|
|
||||||
close(s->msgfd);
|
s->read_msgfds_num = fd_size / sizeof(int);
|
||||||
s->msgfd = fd;
|
s->read_msgfds = g_malloc(fd_size);
|
||||||
|
memcpy(s->read_msgfds, CMSG_DATA(cmsg), fd_size);
|
||||||
|
|
||||||
|
for (i = 0; i < s->read_msgfds_num; i++) {
|
||||||
|
int fd = s->read_msgfds[i];
|
||||||
|
if (fd < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
|
||||||
|
qemu_set_block(fd);
|
||||||
|
|
||||||
|
#ifndef MSG_CMSG_CLOEXEC
|
||||||
|
qemu_set_cloexec(fd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2746,6 +2781,7 @@ static gboolean tcp_chr_accept(GIOChannel *channel, GIOCondition cond, void *opa
|
||||||
static void tcp_chr_close(CharDriverState *chr)
|
static void tcp_chr_close(CharDriverState *chr)
|
||||||
{
|
{
|
||||||
TCPCharDriver *s = chr->opaque;
|
TCPCharDriver *s = chr->opaque;
|
||||||
|
int i;
|
||||||
if (s->fd >= 0) {
|
if (s->fd >= 0) {
|
||||||
remove_fd_in_watch(chr);
|
remove_fd_in_watch(chr);
|
||||||
if (s->chan) {
|
if (s->chan) {
|
||||||
|
@ -2763,6 +2799,12 @@ static void tcp_chr_close(CharDriverState *chr)
|
||||||
}
|
}
|
||||||
closesocket(s->listen_fd);
|
closesocket(s->listen_fd);
|
||||||
}
|
}
|
||||||
|
if (s->read_msgfds_num) {
|
||||||
|
for (i = 0; i < s->read_msgfds_num; i++) {
|
||||||
|
close(s->read_msgfds[i]);
|
||||||
|
}
|
||||||
|
g_free(s->read_msgfds);
|
||||||
|
}
|
||||||
if (s->write_msgfds_num) {
|
if (s->write_msgfds_num) {
|
||||||
g_free(s->write_msgfds);
|
g_free(s->write_msgfds);
|
||||||
}
|
}
|
||||||
|
@ -2794,7 +2836,8 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
|
||||||
s->connected = 0;
|
s->connected = 0;
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
s->listen_fd = -1;
|
s->listen_fd = -1;
|
||||||
s->msgfd = -1;
|
s->read_msgfds = 0;
|
||||||
|
s->read_msgfds_num = 0;
|
||||||
s->write_msgfds = 0;
|
s->write_msgfds = 0;
|
||||||
s->write_msgfds_num = 0;
|
s->write_msgfds_num = 0;
|
||||||
|
|
||||||
|
@ -2827,7 +2870,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
|
||||||
chr->chr_write = tcp_chr_write;
|
chr->chr_write = tcp_chr_write;
|
||||||
chr->chr_sync_read = tcp_chr_sync_read;
|
chr->chr_sync_read = tcp_chr_sync_read;
|
||||||
chr->chr_close = tcp_chr_close;
|
chr->chr_close = tcp_chr_close;
|
||||||
chr->get_msgfd = tcp_get_msgfd;
|
chr->get_msgfds = tcp_get_msgfds;
|
||||||
chr->set_msgfds = tcp_set_msgfds;
|
chr->set_msgfds = tcp_set_msgfds;
|
||||||
chr->chr_add_client = tcp_chr_add_client;
|
chr->chr_add_client = tcp_chr_add_client;
|
||||||
chr->chr_add_watch = tcp_chr_add_watch;
|
chr->chr_add_watch = tcp_chr_add_watch;
|
||||||
|
|
Loading…
Reference in New Issue