aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net.c50
-rw-r--r--net.h2
-rw-r--r--qemu-monitor.hx5
-rw-r--r--qemu-options.hx11
-rw-r--r--slirp/libslirp.h5
-rw-r--r--slirp/slirp.c11
-rw-r--r--slirp/socket.c10
-rw-r--r--slirp/socket.h2
-rw-r--r--slirp/tcp_subr.c15
-rw-r--r--slirp/udp.c7
-rw-r--r--slirp/udp.h2
11 files changed, 73 insertions, 47 deletions
diff --git a/net.c b/net.c
index 883a236638..ee321ab47f 100644
--- a/net.c
+++ b/net.c
@@ -685,7 +685,8 @@ const char *legacy_tftp_prefix;
const char *legacy_bootp_filename;
static VLANClientState *slirp_vc;
-static void slirp_hostfwd(Monitor *mon, const char *redir_str);
+static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+ int legacy_format);
static void slirp_guestfwd(Monitor *mon, const char *config_str,
int legacy_format);
@@ -846,7 +847,8 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
struct slirp_config_str *config = slirp_configs;
if (config->flags & SLIRP_CFG_HOSTFWD) {
- slirp_hostfwd(mon, config->str);
+ slirp_hostfwd(mon, config->str,
+ config->flags & SLIRP_CFG_LEGACY);
} else {
slirp_guestfwd(mon, config->str,
config->flags & SLIRP_CFG_LEGACY);
@@ -871,11 +873,12 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
return 0;
}
-void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
+void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
{
+ struct in_addr host_addr = { .s_addr = INADDR_ANY };
int host_port;
char buf[256] = "";
- const char *p = port_str;
+ const char *p = src_str;
int is_udp = 0;
int n;
@@ -884,7 +887,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
return;
}
- if (!port_str || !port_str[0])
+ if (!src_str || !src_str[0])
goto fail_syntax;
get_str_sep(buf, sizeof(buf), &p, ':');
@@ -897,20 +900,29 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
goto fail_syntax;
}
+ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+ goto fail_syntax;
+ }
+ if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
+ goto fail_syntax;
+ }
+
host_port = atoi(p);
- n = slirp_remove_hostfwd(is_udp, host_port);
+ n = slirp_remove_hostfwd(is_udp, host_addr, host_port);
- monitor_printf(mon, "removed %d host forwarding rules for %s port %d\n",
- n, is_udp ? "udp" : "tcp", host_port);
+ monitor_printf(mon, "removed %d host forwarding rules for %s\n", n,
+ src_str);
return;
fail_syntax:
monitor_printf(mon, "invalid format\n");
}
-static void slirp_hostfwd(Monitor *mon, const char *redir_str)
+static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+ int legacy_format)
{
+ struct in_addr host_addr = { .s_addr = INADDR_ANY };
struct in_addr guest_addr = { .s_addr = 0 };
int host_port, guest_port;
const char *p;
@@ -930,7 +942,16 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str)
goto fail_syntax;
}
- if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+ if (!legacy_format) {
+ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+ goto fail_syntax;
+ }
+ if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
+ goto fail_syntax;
+ }
+ }
+
+ if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
goto fail_syntax;
}
host_port = strtol(buf, &end, 0);
@@ -950,7 +971,8 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str)
goto fail_syntax;
}
- if (slirp_add_hostfwd(is_udp, host_port, guest_addr, guest_port) < 0) {
+ if (slirp_add_hostfwd(is_udp, host_addr, host_port,
+ guest_addr, guest_port) < 0) {
config_error(mon, "could not set up host forwarding rule '%s'\n",
redir_str);
}
@@ -967,7 +989,7 @@ void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str)
return;
}
- slirp_hostfwd(mon, redir_str);
+ slirp_hostfwd(mon, redir_str, 0);
}
void net_slirp_redir(const char *redir_str)
@@ -977,13 +999,13 @@ void net_slirp_redir(const char *redir_str)
if (!slirp_inited) {
config = qemu_malloc(sizeof(*config));
pstrcpy(config->str, sizeof(config->str), redir_str);
- config->flags = SLIRP_CFG_HOSTFWD;
+ config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
config->next = slirp_configs;
slirp_configs = config;
return;
}
- slirp_hostfwd(NULL, redir_str);
+ slirp_hostfwd(NULL, redir_str, 1);
}
#ifndef _WIN32
diff --git a/net.h b/net.h
index 9edfab108e..016db31365 100644
--- a/net.h
+++ b/net.h
@@ -133,7 +133,7 @@ void net_client_uninit(NICInfo *nd);
int net_client_parse(const char *str);
void net_slirp_smb(const char *exported_dir);
void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str);
-void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str);
+void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str);
void net_slirp_redir(const char *redir_str);
void net_cleanup(void);
int slirp_is_inited(void);
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 13c98bc9ac..34f699288a 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -537,10 +537,11 @@ ETEXI
#ifdef CONFIG_SLIRP
{ "hostfwd_add", "s", net_slirp_hostfwd_add,
- "[tcp|udp]:hostport:[guestaddr]:guestport",
+ "[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
"redirect TCP or UDP connections from host to guest (requires -net user)" },
{ "hostfwd_remove", "s", net_slirp_hostfwd_remove,
- "[tcp|udp]:hostport", "remove host-to-guest TCP or UDP redirection" },
+ "[tcp|udp]:[hostaddr]:hostport",
+ "remove host-to-guest TCP or UDP redirection" },
#endif
STEXI
@item host_net_redir
diff --git a/qemu-options.hx b/qemu-options.hx
index da5b0ac6a5..2f21e0a430 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -881,11 +881,12 @@ Note that a SAMBA server must be installed on the host OS in
@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
-@item hostfwd=[tcp|udp]:@var{hostport}:[@var{guestaddr}]:@var{guestport}
+@item hostfwd=[tcp|udp]:[@var{hostaddr}]:@var{hostport}-[@var{guestaddr}]:@var{guestport}
Redirect incoming TCP or UDP connections to the host port @var{hostport} to
the guest IP address @var{guestaddr} on guest port @var{guestport}. If
@var{guestaddr} is not specified, its value is x.x.x.15 (default first address
-given by the built-in DHCP server). If no connection type is specified, TCP is
+given by the built-in DHCP server). By specifying @var{hostaddr}, the rule can
+be bound to a specific host interface. If no connection type is set, TCP is
used. This option can be given multiple times.
For example, to redirect host X11 connection from screen 1 to guest
@@ -893,7 +894,7 @@ screen 0, use the following:
@example
# on the host
-qemu -net user,hostfwd=tcp:6001::6000 [...]
+qemu -net user,hostfwd=tcp:127.0.0.1:6001-:6000 [...]
# this host xterm should open in the guest X11 server
xterm -display :1
@end example
@@ -911,8 +912,8 @@ Then when you use on the host @code{telnet localhost 5555}, you
connect to the guest telnet server.
@item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev}
-Forward guest TCP connections to port @var{port} on the host to character
-device @var{dev}. This option can be given multiple times.
+Forward guest TCP connections to the IP address @var{server} on port @var{port}
+to the character device @var{dev}. This option can be given multiple times.
@end table
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index e4c9c99c3b..9be4425bb6 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -22,10 +22,9 @@ 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_add_hostfwd(int is_udp, int host_port,
+int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
struct in_addr guest_addr, int guest_port);
-int slirp_remove_hostfwd(int is_udp, int host_port);
-
+int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port);
int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
int guest_port);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index ad88121c2c..ab0a8548aa 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -757,7 +757,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
/* Unlistens a redirection
*
* Return value: number of redirs removed */
-int slirp_remove_hostfwd(int is_udp, int host_port)
+int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
{
struct socket *so;
struct socket *head = (is_udp ? &udb : &tcb);
@@ -770,6 +770,7 @@ int slirp_remove_hostfwd(int is_udp, int host_port)
for (so = head->so_next; so != head; so = so->so_next) {
addr_len = sizeof(addr);
if (getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
+ addr.sin_addr.s_addr == host_addr.s_addr &&
addr.sin_port == port) {
close(so->s);
sofree(so);
@@ -781,19 +782,19 @@ int slirp_remove_hostfwd(int is_udp, int host_port)
return n;
}
-int slirp_add_hostfwd(int is_udp, int host_port,
+int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
struct in_addr guest_addr, int guest_port)
{
if (!guest_addr.s_addr) {
guest_addr = vdhcp_startaddr;
}
if (is_udp) {
- if (!udp_listen(htons(host_port), guest_addr.s_addr,
+ if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
htons(guest_port), 0))
return -1;
} else {
- if (!solisten(htons(host_port), guest_addr.s_addr,
- htons(guest_port), 0))
+ if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
+ htons(guest_port), 0))
return -1;
}
return 0;
diff --git a/slirp/socket.c b/slirp/socket.c
index 9f13f03cc6..936021e84d 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -586,17 +586,17 @@ sosendto(struct socket *so, struct mbuf *m)
}
/*
- * XXX This should really be tcp_listen
+ * Listen for incoming TCP connections
*/
struct socket *
-solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
+tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags)
{
struct sockaddr_in addr;
struct socket *so;
int s, opt = 1;
socklen_t addrlen = sizeof(addr);
- DEBUG_CALL("solisten");
+ DEBUG_CALL("tcp_listen");
DEBUG_ARG("port = %d", port);
DEBUG_ARG("laddr = %x", laddr);
DEBUG_ARG("lport = %d", lport);
@@ -625,8 +625,8 @@ solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
so->so_laddr.s_addr = laddr; /* Ditto */
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = port;
+ addr.sin_addr.s_addr = haddr;
+ addr.sin_port = hport;
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
diff --git a/slirp/socket.h b/slirp/socket.h
index f5adaba6e7..ac36aaa4b5 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -82,7 +82,7 @@ int sosendoob _P((struct socket *));
int sowrite _P((struct socket *));
void sorecvfrom _P((struct socket *));
int sosendto _P((struct socket *, struct mbuf *));
-struct socket * solisten _P((u_int, u_int32_t, u_int, int));
+struct socket * tcp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
void soisfconnecting _P((register struct socket *));
void soisfconnected _P((register struct socket *));
void soisfdisconnected _P((struct socket *));
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 858d1ae59c..6fa4223a4e 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -970,7 +970,7 @@ do_prompt:
laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6));
- if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+ if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
n6 = ntohs(so->so_fport);
@@ -1002,7 +1002,7 @@ do_prompt:
laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6));
- if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+ if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
n6 = ntohs(so->so_fport);
@@ -1042,7 +1042,7 @@ do_prompt:
lport += m->m_data[i] - '0';
}
if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
- (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
+ (so = tcp_listen(INADDR_ANY, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
ntohs(so->so_fport)) + 1;
return 1;
@@ -1057,7 +1057,7 @@ do_prompt:
/* The %256s is for the broken mIRC */
if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
- if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+ if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1066,7 +1066,7 @@ do_prompt:
(unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), 1);
} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
- if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+ if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1075,7 +1075,7 @@ do_prompt:
(unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), n1, 1);
} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
- if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+ if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1190,7 +1190,8 @@ do_prompt:
/* try to get udp port between 6970 - 7170 */
for (p = 6970; p < 7071; p++) {
- if (udp_listen( htons(p),
+ if (udp_listen(INADDR_ANY,
+ htons(p),
so->so_laddr.s_addr,
htons(lport),
SS_FACCEPTONCE)) {
diff --git a/slirp/udp.c b/slirp/udp.c
index ff3a39fb21..d675ad3e66 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -627,7 +627,8 @@ struct cu_header {
}
struct socket *
-udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
+udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
+ int flags)
{
struct sockaddr_in addr;
struct socket *so;
@@ -642,8 +643,8 @@ udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
insque(so,&udb);
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = port;
+ addr.sin_addr.s_addr = haddr;
+ addr.sin_port = hport;
if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
udp_detach(so);
diff --git a/slirp/udp.h b/slirp/udp.h
index 51a07a2fcc..d4c2bea60e 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -101,7 +101,7 @@ void udp_input _P((register struct mbuf *, int));
int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
int udp_attach _P((struct socket *));
void udp_detach _P((struct socket *));
-struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
+struct socket * udp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
int udp_output2(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
int iptos);