User Networking: Enable removal of redirections

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>
This commit is contained in:
Alexander Graf 2009-05-26 13:03:26 +02:00 committed by Anthony Liguori
parent 8a43b1ea7f
commit c1261d8d16
6 changed files with 71 additions and 5 deletions

View File

@ -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)" },

43
net.c
View File

@ -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;

2
net.h
View File

@ -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);

View 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,

View 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)
{

2
vl.c
View File

@ -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: