Commit c1261d8d1617d8cf5722039a59ebb66c310f3aea

Authored by Alexander Graf
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>
monitor.c
... ... @@ -1759,8 +1759,9 @@ static const mon_cmd_t mon_cmds[] = {
1759 1759 { "host_net_remove", "is", net_host_device_remove,
1760 1760 "vlan_id name", "remove host VLAN client" },
1761 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 1765 #endif
1765 1766 { "balloon", "i", do_balloon,
1766 1767 "target", "request VM to change it's memory allocation (in MB)" },
... ...
... ... @@ -568,7 +568,43 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
568 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 609 int is_udp;
574 610 char buf[256], *r;
... ... @@ -581,6 +617,11 @@ void net_slirp_redir(Monitor *mon, const char *redir_str)
581 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 625 p = redir_str;
585 626 if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
586 627 goto fail_syntax;
... ...
... ... @@ -112,7 +112,7 @@ int net_client_init(const char *device, const char *p);
112 112 void net_client_uninit(NICInfo *nd);
113 113 int net_client_parse(const char *str);
114 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 116 void net_cleanup(void);
117 117 int slirp_is_inited(void);
118 118 void net_client_check(void);
... ...
slirp/libslirp.h
... ... @@ -18,6 +18,7 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
18 18 int slirp_can_output(void);
19 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 22 int slirp_redir(int is_udp, int host_port,
22 23 struct in_addr guest_addr, int guest_port);
23 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 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 760 int slirp_redir(int is_udp, int host_port,
738 761 struct in_addr guest_addr, int guest_port)
739 762 {
... ...
... ... @@ -5152,7 +5152,7 @@ int main(int argc, char **argv, char **envp)
5152 5152 break;
5153 5153 #endif
5154 5154 case QEMU_OPTION_redir:
5155   - net_slirp_redir(NULL, optarg);
  5155 + net_slirp_redir(NULL, optarg, NULL);
5156 5156 break;
5157 5157 #endif
5158 5158 case QEMU_OPTION_bt:
... ...