User Networking: Enable removal of redirections
authorAlexander Graf <agraf@suse.de>
Tue, 26 May 2009 11:03:26 +0000 (13:03 +0200)
committerAnthony Liguori <aliguori@us.ibm.com>
Wed, 27 May 2009 14:46:12 +0000 (09:46 -0500)
Using the new host_net_redir command you can easily create redirections
on the fly while your VM is running.

While that's great, it's missing the removal of redirections, in case you
want to have a port closed again at a later point in time.

This patch adds support for removal of redirections.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

monitor.c
net.c
net.h
slirp/libslirp.h
slirp/slirp.c
vl.c

index 0f38c71..dbab3de 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -1759,8 +1759,9 @@ static const mon_cmd_t mon_cmds[] = {
     { "host_net_remove", "is", net_host_device_remove,
       "vlan_id name", "remove host VLAN client" },
 #ifdef CONFIG_SLIRP
-    { "host_net_redir", "s", net_slirp_redir,
-      "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)" },
+    { "host_net_redir", "ss?", net_slirp_redir,
+      "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)\n"
+      "host_net_redir remove [tcp:|udp:]host-port -- remove redirection" },
 #endif
     { "balloon", "i", do_balloon,
       "target", "request VM to change it's memory allocation (in MB)" },
diff --git a/net.c b/net.c
index 88823b8..9f5b79b 100644 (file)
--- a/net.c
+++ b/net.c
@@ -568,7 +568,43 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
     return 0;
 }
 
-void net_slirp_redir(Monitor *mon, const char *redir_str)
+static void net_slirp_redir_rm(Monitor *mon, const char *port_str)
+{
+    int host_port;
+    char buf[256] = "";
+    const char *p = port_str;
+    int is_udp = 0;
+    int n;
+
+    if (!mon)
+        return;
+
+    if (!port_str || !port_str[0])
+        goto fail_syntax;
+
+    get_str_sep(buf, sizeof(buf), &p, ':');
+
+    if (!strcmp(buf, "tcp") || buf[0] == '\0') {
+        is_udp = 0;
+    } else if (!strcmp(buf, "udp")) {
+        is_udp = 1;
+    } else {
+        goto fail_syntax;
+    }
+
+    host_port = atoi(p);
+
+    n = slirp_redir_rm(is_udp, host_port);
+
+    monitor_printf(mon, "removed %d redirections to %s port %d\n", n,
+                        is_udp ? "udp" : "tcp", host_port);
+    return;
+
+ fail_syntax:
+    monitor_printf(mon, "invalid format\n");
+}
+
+void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2)
 {
     int is_udp;
     char buf[256], *r;
@@ -581,6 +617,11 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
         slirp_init(slirp_restrict, slirp_ip);
     }
 
+    if (!strcmp(redir_str, "remove")) {
+        net_slirp_redir_rm(mon, redir_opt2);
+        return;
+    }
+
     p = redir_str;
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
         goto fail_syntax;
diff --git a/net.h b/net.h
index 41a3082..feee021 100644 (file)
--- a/net.h
+++ b/net.h
@@ -112,7 +112,7 @@ int net_client_init(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_redir(Monitor *mon, const char *redir_str);
+void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2);
 void net_cleanup(void);
 int slirp_is_inited(void);
 void net_client_check(void);
index a1cd70e..6fc2c32 100644 (file)
@@ -18,6 +18,7 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
 int slirp_can_output(void);
 void slirp_output(const uint8_t *pkt, int pkt_len);
 
+int slirp_redir_rm(int is_udp, int host_port);
 int slirp_redir(int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port);
 int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
index 04d3ded..33397c0 100644 (file)
@@ -734,6 +734,29 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
     }
 }
 
+/* Unlistens a redirection
+ *
+ * Return value: number of redirs removed */
+int slirp_redir_rm(int is_udp, int host_port)
+{
+    struct socket *so;
+    struct socket *head = (is_udp ? &udb : &tcb);
+    int fport = htons(host_port);
+    int n = 0;
+
+ loop_again:
+    for (so = head->so_next; so != head; so = so->so_next) {
+        if (so->so_fport == fport) {
+            close(so->s);
+            sofree(so);
+            n++;
+            goto loop_again;
+        }
+    }
+
+    return n;
+}
+
 int slirp_redir(int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port)
 {
diff --git a/vl.c b/vl.c
index 0d6c85b..8ab1665 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -5152,7 +5152,7 @@ int main(int argc, char **argv, char **envp)
                 break;
 #endif
             case QEMU_OPTION_redir:
-                net_slirp_redir(NULL, optarg);
+                net_slirp_redir(NULL, optarg, NULL);
                 break;
 #endif
             case QEMU_OPTION_bt: