From f13b572cb38ec8c74a0670b3554d48e7cbf20b4b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 24 Jun 2009 14:42:32 +0200 Subject: [PATCH] slirp: Make hostfwd_add/remove multi-instance-aware Extend the syntax of hostfwd_add/remove to optionally take a tuple of VLAN ID and slirp stack name. If those are omitted, the commands will continue to work on the first registered slirp stack. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- net.c | 62 +++++++++++++++++++++++++++++++++++++++++-------- net.h | 6 +++-- qemu-monitor.hx | 8 +++---- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/net.c b/net.c index 918379428..8c80b0b7c 100644 --- a/net.c +++ b/net.c @@ -907,23 +907,56 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model, return 0; } -void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str) +static SlirpState *slirp_lookup(Monitor *mon, const char *vlan, + const char *stack) +{ + VLANClientState *vc; + + if (vlan) { + vc = qemu_find_vlan_client_by_name(mon, strtol(vlan, NULL, 0), stack); + if (!vc) { + return NULL; + } + if (strcmp(vc->model, "user")) { + monitor_printf(mon, "invalid device specified\n"); + return NULL; + } + return vc->opaque; + } else { + if (TAILQ_EMPTY(&slirp_stacks)) { + monitor_printf(mon, "user mode network stack not in use\n"); + return NULL; + } + return TAILQ_FIRST(&slirp_stacks); + } +} + +void net_slirp_hostfwd_remove(Monitor *mon, const char *arg1, + const char *arg2, const char *arg3) { struct in_addr host_addr = { .s_addr = INADDR_ANY }; int host_port; char buf[256] = ""; - const char *p = src_str; + const char *src_str, *p; + SlirpState *s; int is_udp = 0; int err; - if (TAILQ_EMPTY(&slirp_stacks)) { - monitor_printf(mon, "user mode network stack not in use\n"); + if (arg2) { + s = slirp_lookup(mon, arg1, arg2); + src_str = arg3; + } else { + s = slirp_lookup(mon, NULL, NULL); + src_str = arg1; + } + if (!s) { return; } if (!src_str || !src_str[0]) goto fail_syntax; + p = src_str; get_str_sep(buf, sizeof(buf), &p, ':'); if (!strcmp(buf, "tcp") || buf[0] == '\0') { @@ -966,7 +999,7 @@ static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str, char *end; p = redir_str; - if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { + if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) { goto fail_syntax; } if (!strcmp(buf, "tcp") || buf[0] == '\0') { @@ -1017,14 +1050,23 @@ static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str, config_error(mon, "invalid host forwarding rule '%s'\n", redir_str); } -void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str) +void net_slirp_hostfwd_add(Monitor *mon, const char *arg1, + const char *arg2, const char *arg3) { - if (TAILQ_EMPTY(&slirp_stacks)) { - monitor_printf(mon, "user mode network stack not in use\n"); - return; + const char *redir_str; + SlirpState *s; + + if (arg2) { + s = slirp_lookup(mon, arg1, arg2); + redir_str = arg3; + } else { + s = slirp_lookup(mon, NULL, NULL); + redir_str = arg1; + } + if (s) { + slirp_hostfwd(s, mon, redir_str, 0); } - slirp_hostfwd(TAILQ_FIRST(&slirp_stacks), mon, redir_str, 0); } void net_slirp_redir(const char *redir_str) diff --git a/net.h b/net.h index a5ae730a5..64d5e22f1 100644 --- a/net.h +++ b/net.h @@ -134,8 +134,10 @@ int net_client_init(Monitor *mon, const char *device, const char *p); void net_client_uninit(NICInfo *nd); int net_client_parse(const char *str); void net_slirp_smb(const char *exported_dir); -void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str); -void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str); +void net_slirp_hostfwd_add(Monitor *mon, const char *arg1, + const char *arg2, const char *arg3); +void net_slirp_hostfwd_remove(Monitor *mon, const char *arg1, + const char *arg2, const char *arg3); void net_slirp_redir(const char *redir_str); void net_cleanup(void); void net_client_check(void); diff --git a/qemu-monitor.hx b/qemu-monitor.hx index e320f9f2f..66c6ad901 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -536,11 +536,11 @@ Remove host VLAN client. ETEXI #ifdef CONFIG_SLIRP - { "hostfwd_add", "s", net_slirp_hostfwd_add, - "[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport", + { "hostfwd_add", "ss?s?", net_slirp_hostfwd_add, + "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport", "redirect TCP or UDP connections from host to guest (requires -net user)" }, - { "hostfwd_remove", "s", net_slirp_hostfwd_remove, - "[tcp|udp]:[hostaddr]:hostport", + { "hostfwd_remove", "ss?s?", net_slirp_hostfwd_remove, + "[vlan_id name] [tcp|udp]:[hostaddr]:hostport", "remove host-to-guest TCP or UDP redirection" }, #endif STEXI