Commit c1261d8d1617d8cf5722039a59ebb66c310f3aea
Committed by
Anthony Liguori
1 parent
8a43b1ea
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>
Showing
6 changed files
with
71 additions
and
5 deletions
monitor.c
| @@ -1759,8 +1759,9 @@ static const mon_cmd_t mon_cmds[] = { | @@ -1759,8 +1759,9 @@ static const mon_cmd_t mon_cmds[] = { | ||
| 1759 | { "host_net_remove", "is", net_host_device_remove, | 1759 | { "host_net_remove", "is", net_host_device_remove, |
| 1760 | "vlan_id name", "remove host VLAN client" }, | 1760 | "vlan_id name", "remove host VLAN client" }, |
| 1761 | #ifdef CONFIG_SLIRP | 1761 | #ifdef CONFIG_SLIRP |
| 1762 | - { "host_net_redir", "s", net_slirp_redir, | ||
| 1763 | - "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)" }, | 1762 | + { "host_net_redir", "ss?", net_slirp_redir, |
| 1763 | + "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)\n" | ||
| 1764 | + "host_net_redir remove [tcp:|udp:]host-port -- remove redirection" }, | ||
| 1764 | #endif | 1765 | #endif |
| 1765 | { "balloon", "i", do_balloon, | 1766 | { "balloon", "i", do_balloon, |
| 1766 | "target", "request VM to change it's memory allocation (in MB)" }, | 1767 | "target", "request VM to change it's memory allocation (in MB)" }, |
net.c
| @@ -568,7 +568,43 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name) | @@ -568,7 +568,43 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name) | ||
| 568 | return 0; | 568 | return 0; |
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | -void net_slirp_redir(Monitor *mon, const char *redir_str) | 571 | +static void net_slirp_redir_rm(Monitor *mon, const char *port_str) |
| 572 | +{ | ||
| 573 | + int host_port; | ||
| 574 | + char buf[256] = ""; | ||
| 575 | + const char *p = port_str; | ||
| 576 | + int is_udp = 0; | ||
| 577 | + int n; | ||
| 578 | + | ||
| 579 | + if (!mon) | ||
| 580 | + return; | ||
| 581 | + | ||
| 582 | + if (!port_str || !port_str[0]) | ||
| 583 | + goto fail_syntax; | ||
| 584 | + | ||
| 585 | + get_str_sep(buf, sizeof(buf), &p, ':'); | ||
| 586 | + | ||
| 587 | + if (!strcmp(buf, "tcp") || buf[0] == '\0') { | ||
| 588 | + is_udp = 0; | ||
| 589 | + } else if (!strcmp(buf, "udp")) { | ||
| 590 | + is_udp = 1; | ||
| 591 | + } else { | ||
| 592 | + goto fail_syntax; | ||
| 593 | + } | ||
| 594 | + | ||
| 595 | + host_port = atoi(p); | ||
| 596 | + | ||
| 597 | + n = slirp_redir_rm(is_udp, host_port); | ||
| 598 | + | ||
| 599 | + monitor_printf(mon, "removed %d redirections to %s port %d\n", n, | ||
| 600 | + is_udp ? "udp" : "tcp", host_port); | ||
| 601 | + return; | ||
| 602 | + | ||
| 603 | + fail_syntax: | ||
| 604 | + monitor_printf(mon, "invalid format\n"); | ||
| 605 | +} | ||
| 606 | + | ||
| 607 | +void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2) | ||
| 572 | { | 608 | { |
| 573 | int is_udp; | 609 | int is_udp; |
| 574 | char buf[256], *r; | 610 | char buf[256], *r; |
| @@ -581,6 +617,11 @@ void net_slirp_redir(Monitor *mon, const char *redir_str) | @@ -581,6 +617,11 @@ void net_slirp_redir(Monitor *mon, const char *redir_str) | ||
| 581 | slirp_init(slirp_restrict, slirp_ip); | 617 | slirp_init(slirp_restrict, slirp_ip); |
| 582 | } | 618 | } |
| 583 | 619 | ||
| 620 | + if (!strcmp(redir_str, "remove")) { | ||
| 621 | + net_slirp_redir_rm(mon, redir_opt2); | ||
| 622 | + return; | ||
| 623 | + } | ||
| 624 | + | ||
| 584 | p = redir_str; | 625 | p = redir_str; |
| 585 | if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | 626 | if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) |
| 586 | goto fail_syntax; | 627 | goto fail_syntax; |
net.h
| @@ -112,7 +112,7 @@ int net_client_init(const char *device, const char *p); | @@ -112,7 +112,7 @@ int net_client_init(const char *device, const char *p); | ||
| 112 | void net_client_uninit(NICInfo *nd); | 112 | void net_client_uninit(NICInfo *nd); |
| 113 | int net_client_parse(const char *str); | 113 | int net_client_parse(const char *str); |
| 114 | void net_slirp_smb(const char *exported_dir); | 114 | void net_slirp_smb(const char *exported_dir); |
| 115 | -void net_slirp_redir(Monitor *mon, const char *redir_str); | 115 | +void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2); |
| 116 | void net_cleanup(void); | 116 | void net_cleanup(void); |
| 117 | int slirp_is_inited(void); | 117 | int slirp_is_inited(void); |
| 118 | void net_client_check(void); | 118 | void net_client_check(void); |
slirp/libslirp.h
| @@ -18,6 +18,7 @@ void slirp_input(const uint8_t *pkt, int pkt_len); | @@ -18,6 +18,7 @@ void slirp_input(const uint8_t *pkt, int pkt_len); | ||
| 18 | int slirp_can_output(void); | 18 | int slirp_can_output(void); |
| 19 | void slirp_output(const uint8_t *pkt, int pkt_len); | 19 | void slirp_output(const uint8_t *pkt, int pkt_len); |
| 20 | 20 | ||
| 21 | +int slirp_redir_rm(int is_udp, int host_port); | ||
| 21 | int slirp_redir(int is_udp, int host_port, | 22 | int slirp_redir(int is_udp, int host_port, |
| 22 | struct in_addr guest_addr, int guest_port); | 23 | struct in_addr guest_addr, int guest_port); |
| 23 | int slirp_add_exec(int do_pty, const void *args, int addr_low_byte, | 24 | int slirp_add_exec(int do_pty, const void *args, int addr_low_byte, |
slirp/slirp.c
| @@ -734,6 +734,29 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) | @@ -734,6 +734,29 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) | ||
| 734 | } | 734 | } |
| 735 | } | 735 | } |
| 736 | 736 | ||
| 737 | +/* Unlistens a redirection | ||
| 738 | + * | ||
| 739 | + * Return value: number of redirs removed */ | ||
| 740 | +int slirp_redir_rm(int is_udp, int host_port) | ||
| 741 | +{ | ||
| 742 | + struct socket *so; | ||
| 743 | + struct socket *head = (is_udp ? &udb : &tcb); | ||
| 744 | + int fport = htons(host_port); | ||
| 745 | + int n = 0; | ||
| 746 | + | ||
| 747 | + loop_again: | ||
| 748 | + for (so = head->so_next; so != head; so = so->so_next) { | ||
| 749 | + if (so->so_fport == fport) { | ||
| 750 | + close(so->s); | ||
| 751 | + sofree(so); | ||
| 752 | + n++; | ||
| 753 | + goto loop_again; | ||
| 754 | + } | ||
| 755 | + } | ||
| 756 | + | ||
| 757 | + return n; | ||
| 758 | +} | ||
| 759 | + | ||
| 737 | int slirp_redir(int is_udp, int host_port, | 760 | int slirp_redir(int is_udp, int host_port, |
| 738 | struct in_addr guest_addr, int guest_port) | 761 | struct in_addr guest_addr, int guest_port) |
| 739 | { | 762 | { |
vl.c
| @@ -5152,7 +5152,7 @@ int main(int argc, char **argv, char **envp) | @@ -5152,7 +5152,7 @@ int main(int argc, char **argv, char **envp) | ||
| 5152 | break; | 5152 | break; |
| 5153 | #endif | 5153 | #endif |
| 5154 | case QEMU_OPTION_redir: | 5154 | case QEMU_OPTION_redir: |
| 5155 | - net_slirp_redir(NULL, optarg); | 5155 | + net_slirp_redir(NULL, optarg, NULL); |
| 5156 | break; | 5156 | break; |
| 5157 | #endif | 5157 | #endif |
| 5158 | case QEMU_OPTION_bt: | 5158 | case QEMU_OPTION_bt: |