diff --git a/monitor.c b/monitor.c index dbab3de827..443f6d47c2 100644 --- a/monitor.c +++ b/monitor.c @@ -1761,7 +1761,8 @@ static const mon_cmd_t mon_cmds[] = { #ifdef CONFIG_SLIRP { "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" }, + "host_net_redir remove [tcp:|udp:]host-port -- remove redirection\n" + "host_net_redir list -- show all redirections" }, #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 9f5b79bc49..2d24a7ce5f 100644 --- a/net.c +++ b/net.c @@ -568,6 +568,45 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name) return 0; } +static void net_slirp_redir_print(void *opaque, int is_udp, + struct in_addr *laddr, u_int lport, + struct in_addr *faddr, u_int fport) +{ + Monitor *mon = (Monitor *)opaque; + uint32_t h_addr; + uint32_t g_addr; + char buf[16]; + + h_addr = ntohl(faddr->s_addr); + g_addr = ntohl(laddr->s_addr); + + monitor_printf(mon, " %s |", is_udp ? "udp" : "tcp" ); + snprintf(buf, 15, "%d.%d.%d.%d", (h_addr >> 24) & 0xff, + (h_addr >> 16) & 0xff, + (h_addr >> 8) & 0xff, + (h_addr) & 0xff); + monitor_printf(mon, " %15s |", buf); + monitor_printf(mon, " %5d |", fport); + + snprintf(buf, 15, "%d.%d.%d.%d", (g_addr >> 24) & 0xff, + (g_addr >> 16) & 0xff, + (g_addr >> 8) & 0xff, + (g_addr) & 0xff); + monitor_printf(mon, " %15s |", buf); + monitor_printf(mon, " %5d\n", lport); + +} + +static void net_slirp_redir_list(Monitor *mon) +{ + if (!mon) + return; + + monitor_printf(mon, " Prot | Host Addr | HPort | Guest Addr | GPort\n"); + monitor_printf(mon, " | | | | \n"); + slirp_redir_loop(net_slirp_redir_print, mon); +} + static void net_slirp_redir_rm(Monitor *mon, const char *port_str) { int host_port; @@ -622,6 +661,11 @@ void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2 return; } + if (!strcmp(redir_str, "list")) { + net_slirp_redir_list(mon); + return; + } + p = redir_str; if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) goto fail_syntax; diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 6fc2c329ad..b2313b43c6 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -18,6 +18,10 @@ 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); +void slirp_redir_loop(void (*func)(void *opaque, int is_udp, + struct in_addr *laddr, u_int lport, + struct in_addr *faddr, u_int fport), + void *opaque); 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); diff --git a/slirp/slirp.c b/slirp/slirp.c index 33397c07dc..9cab73124e 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -734,6 +734,30 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) } } +static void _slirp_redir_loop(void (*func)(void *opaque, int is_udp, + struct in_addr *laddr, u_int lport, + struct in_addr *faddr, u_int fport), + void *opaque, int is_udp) +{ + struct socket *head = (is_udp ? &udb : &tcb); + struct socket *so; + + for (so = head->so_next; so != head; so = so->so_next) { + func(opaque, is_udp, + &so->so_laddr, ntohs(so->so_lport), + &so->so_faddr, ntohs(so->so_fport)); + } +} + +void slirp_redir_loop(void (*func)(void *opaque, int is_udp, + struct in_addr *laddr, u_int lport, + struct in_addr *faddr, u_int fport), + void *opaque) +{ + _slirp_redir_loop(func, opaque, 0); + _slirp_redir_loop(func, opaque, 1); +} + /* Unlistens a redirection * * Return value: number of redirs removed */