diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2019-01-17 15:43:33 +0400 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2019-02-07 15:49:08 +0200 |
commit | 44b4ff248802d957b819ae49c66a29f311078213 (patch) | |
tree | 8d5508512383aa5801602702df68eaffe368943a | |
parent | aaa0c642b1de62d5a69b6d4bfdaa91e4b65c5518 (diff) |
slirp: generalize guestfwd with a callback based approach
Instead of calling into QEMU chardev directly, and mixing it with
slirp_add_exec() handling, add a new function slirp_add_guestfwd()
which takes a write callback.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
-rw-r--r-- | net/slirp.c | 14 | ||||
-rw-r--r-- | slirp/libslirp.h | 6 | ||||
-rw-r--r-- | slirp/misc.c | 37 | ||||
-rw-r--r-- | slirp/misc.h | 15 | ||||
-rw-r--r-- | slirp/slirp.c | 27 | ||||
-rw-r--r-- | slirp/socket.h | 4 | ||||
-rw-r--r-- | slirp/tcp_subr.c | 4 |
7 files changed, 75 insertions, 32 deletions
diff --git a/net/slirp.c b/net/slirp.c index f98425ee9f..ec07f662c0 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -704,8 +704,8 @@ static int slirp_smb(SlirpState* s, const char *exported_dir, CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf); g_free(smb_conf); - if (slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 139) < 0 || - slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 445) < 0) { + if (slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 139) < 0 || + slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 445) < 0) { slirp_smb_cleanup(s); g_free(smb_cmdline); error_setg(errp, "Conflicting/invalid smbserver address"); @@ -736,6 +736,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size) slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size); } +static int guestfwd_write(const void *buf, size_t len, void *chr) +{ + return qemu_chr_fe_write_all(chr, buf, len); +} + static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp) { struct in_addr server = { .s_addr = 0 }; @@ -769,7 +774,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp) snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port); if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) { - if (slirp_add_exec(s->slirp, NULL, &p[4], &server, port) < 0) { + if (slirp_add_exec(s->slirp, &p[4], &server, port) < 0) { error_setg(errp, "Conflicting/invalid host:port in guest " "forwarding rule '%s'", config_str); return -1; @@ -796,7 +801,8 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp) return -1; } - if (slirp_add_exec(s->slirp, &fwd->hd, NULL, &server, port) < 0) { + if (slirp_add_guestfwd(s->slirp, guestfwd_write, &fwd->hd, + &server, port) < 0) { error_setg(errp, "Conflicting/invalid host:port in guest " "forwarding rule '%s'", config_str); g_free(fwd); diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 4611a7447b..ea019828e8 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -5,6 +5,8 @@ typedef struct Slirp Slirp; +typedef int (*SlirpWriteCb)(const void *buf, size_t len, void *opaque); + /* * Callbacks from slirp * @@ -45,7 +47,9 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr guest_addr, int guest_port); int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, int host_port); -int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline, +int slirp_add_exec(Slirp *slirp, const char *cmdline, + struct in_addr *guest_addr, int guest_port); +int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque, struct in_addr *guest_addr, int guest_port); char *slirp_connection_info(Slirp *slirp); diff --git a/slirp/misc.c b/slirp/misc.c index eae9596a55..b8a2bf971a 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -32,24 +32,33 @@ remque(void *a) element->qh_rlink = NULL; } -int add_exec(struct gfwd_list **ex_ptr, void *chardev, const char *cmdline, +struct gfwd_list * +add_guestfwd(struct gfwd_list **ex_ptr, + SlirpWriteCb write_cb, void *opaque, struct in_addr addr, int port) { - struct gfwd_list *tmp_ptr; - - tmp_ptr = *ex_ptr; - *ex_ptr = g_new0(struct gfwd_list, 1); - (*ex_ptr)->ex_fport = port; - (*ex_ptr)->ex_addr = addr; - if (chardev) { - (*ex_ptr)->ex_chardev = chardev; - } else { - (*ex_ptr)->ex_exec = g_strdup(cmdline); - } - (*ex_ptr)->ex_next = tmp_ptr; - return 0; + struct gfwd_list *f = g_new0(struct gfwd_list, 1); + + f->write_cb = write_cb; + f->opaque = opaque; + f->ex_fport = port; + f->ex_addr = addr; + f->ex_next = *ex_ptr; + *ex_ptr = f; + + return f; } +struct gfwd_list * +add_exec(struct gfwd_list **ex_ptr, const char *cmdline, + struct in_addr addr, int port) +{ + struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port); + + f->ex_exec = g_strdup(cmdline); + + return f; +} static int slirp_socketpair_with_oob(int sv[2]) diff --git a/slirp/misc.h b/slirp/misc.h index 1df707c052..c2ceadb591 100644 --- a/slirp/misc.h +++ b/slirp/misc.h @@ -8,8 +8,11 @@ #ifndef MISC_H #define MISC_H +#include "libslirp.h" + struct gfwd_list { - void *ex_chardev; + SlirpWriteCb write_cb; + void *opaque; struct in_addr ex_addr; /* Server address */ int ex_fport; /* Port to telnet to */ char *ex_exec; /* Command line of what to exec */ @@ -51,7 +54,15 @@ struct slirp_quehead { void slirp_insque(void *, void *); void slirp_remque(void *); -int add_exec(struct gfwd_list **, void *, const char *, struct in_addr, int); int fork_exec(struct socket *so, const char *ex); +struct gfwd_list * +add_guestfwd(struct gfwd_list **ex_ptr, + SlirpWriteCb write_cb, void *opaque, + struct in_addr addr, int port); + +struct gfwd_list * +add_exec(struct gfwd_list **ex_ptr, const char *cmdline, + struct in_addr addr, int port); + #endif diff --git a/slirp/slirp.c b/slirp/slirp.c index 739f364770..a411221914 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -25,7 +25,6 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "qemu/error-report.h" -#include "chardev/char-fe.h" #include "migration/register.h" #include "slirp.h" #include "hw/hw.h" @@ -1068,23 +1067,35 @@ check_guestfwd(Slirp *slirp, struct in_addr *guest_addr, int guest_port) return true; } -int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline, +int slirp_add_exec(Slirp *slirp, const char *cmdline, struct in_addr *guest_addr, int guest_port) { if (!check_guestfwd(slirp, guest_addr, guest_port)) { return -1; } - return add_exec(&slirp->guestfwd_list, chardev, cmdline, *guest_addr, - htons(guest_port)); + add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port)); + return 0; +} + +int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque, + struct in_addr *guest_addr, int guest_port) +{ + if (!check_guestfwd(slirp, guest_addr, guest_port)) { + return -1; + } + + add_guestfwd(&slirp->guestfwd_list, write_cb, opaque, + *guest_addr, htons(guest_port)); + return 0; } ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) { - if (so->s == -1 && so->chardev) { + if (so->s == -1 && so->guestfwd) { /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ - qemu_chr_fe_write_all(so->chardev, buf, len); + so->guestfwd->write_cb(buf, len, so->guestfwd->opaque); return len; } @@ -1449,7 +1460,7 @@ static void slirp_state_save(QEMUFile *f, void *opaque) struct gfwd_list *ex_ptr; for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) - if (ex_ptr->ex_chardev) { + if (ex_ptr->write_cb) { struct socket *so; so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport)); @@ -1484,7 +1495,7 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; } for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_chardev && + if (ex_ptr->write_cb && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr && so->so_fport == ex_ptr->ex_fport) { break; diff --git a/slirp/socket.h b/slirp/socket.h index 930ed95972..fc35ca5f72 100644 --- a/slirp/socket.h +++ b/slirp/socket.h @@ -8,6 +8,8 @@ #ifndef SLIRP_SOCKET_H #define SLIRP_SOCKET_H +#include "misc.h" + #define SO_EXPIRE 240000 #define SO_EXPIREFAST 10000 @@ -25,6 +27,7 @@ struct socket { struct socket *so_next,*so_prev; /* For a linked list of sockets */ int s; /* The actual socket */ + struct gfwd_list *guestfwd; int pollfds_idx; /* GPollFD GArray index */ @@ -67,7 +70,6 @@ struct socket { struct sbuf so_rcv; /* Receive buffer */ struct sbuf so_snd; /* Send buffer */ - void * chardev; }; diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 23a841f26e..4e81736d6f 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -964,9 +964,9 @@ int tcp_ctl(struct socket *so) for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == so->so_fport && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { - if (ex_ptr->ex_chardev) { + if (ex_ptr->write_cb) { so->s = -1; - so->chardev = ex_ptr->ex_chardev; + so->guestfwd = ex_ptr; return 1; } DEBUG_MISC(" executing %s", ex_ptr->ex_exec); |