port redirection support

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1054 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2004-08-25 22:12:49 +00:00
parent a3504c87ca
commit 9bf05444b2
7 changed files with 149 additions and 9 deletions

View File

@ -9,6 +9,7 @@ version 0.6.1:
- VMware 3 and 4 read-only disk image support (untested) - VMware 3 and 4 read-only disk image support (untested)
- Support for up to 4 serial ports - Support for up to 4 serial ports
- TFTP server support (Magnus Damm) - TFTP server support (Magnus Damm)
- Port redirection support in user mode networking
version 0.6.0: version 0.6.0:

View File

@ -228,6 +228,44 @@ example of its use.
Use the user mode network stack. This is the default if no tun/tap Use the user mode network stack. This is the default if no tun/tap
network init script is found. network init script is found.
@item -tftp prefix
When using the user mode network stack, activate a built-in TFTP
server. All filenames beginning with @var{prefix} can be downloaded
from the host to the guest using a TFTP client. The TFTP client on the
guest must be configured in binary mode (use the command @code{bin} of
the Unix TFTP client). The host IP address on the guest is as usual
10.0.2.2.
@item -redir [tcp|udp]:host-port:[guest-host]:guest-port
When using the user mode network stack, redirect incoming TCP or UDP
connections to the host port @var{host-port} to the guest
@var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
is not specified, its value is 10.0.2.15 (default address given by the
built-in DHCP server).
For example, to redirect host X11 connection from screen 1 to guest
screen 0, use the following:
@example
# on the host
qemu -redir tcp:6001::6000 [...]
# this host xterm should open in the guest X11 server
xterm -display :1
@end example
To redirect telnet connections from host port 5555 to telnet port on
the guest, use the following:
@example
# on the host
qemu -redir tcp:5555::23 [...]
telnet localhost 5555
@end example
Then when you use on the host @code{telnet localhost 5555}, you
connect to the guest telnet server.
@item -dummy-net @item -dummy-net
Use the dummy network stack: no packet will be received by the network Use the dummy network stack: no packet will be received by the network
cards. cards.
@ -652,7 +690,12 @@ Note that @code{ping} is not supported reliably to the internet as it
would require root priviledges. It means you can only ping the local would require root priviledges. It means you can only ping the local
router (10.0.2.2). router (10.0.2.2).
The user mode network is currently only supported on a Unix host. When using the built-in TFTP server, the router is also the TFTP
server.
When using the @option{-redir} option, TCP or UDP connections can be
redirected from the host to the guest. It allows for example to
redirect X11, telnet or SSH connections.
@node direct_linux_boot @node direct_linux_boot
@section Direct Linux Boot @section Direct Linux Boot

View File

@ -3,8 +3,10 @@
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
int inet_aton(const char *cp, struct in_addr *ia);
#else #else
#include <sys/select.h> #include <sys/select.h>
#include <arpa/inet.h>
#endif #endif
void slirp_init(void); void slirp_init(void);
@ -20,4 +22,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
int slirp_can_output(void); int slirp_can_output(void);
void slirp_output(const uint8_t *pkt, int pkt_len); void slirp_output(const uint8_t *pkt, int pkt_len);
int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port);
extern const char *tftp_prefix;
#endif #endif

View File

@ -617,3 +617,18 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
slirp_output(buf, ip_data_len + ETH_HLEN); slirp_output(buf, ip_data_len + ETH_HLEN);
} }
int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port)
{
if (is_udp) {
if (!udp_listen(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))
return -1;
}
return 0;
}

View File

@ -36,7 +36,7 @@ struct tftp_session {
struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
char *tftp_prefix; const char *tftp_prefix;
static void tftp_session_update(struct tftp_session *spt) static void tftp_session_update(struct tftp_session *spt)
{ {

View File

@ -29,6 +29,4 @@ struct tftp_t {
} x; } x;
}; };
extern char *tftp_prefix;
void tftp_input(struct mbuf *m); void tftp_input(struct mbuf *m);

86
vl.c
View File

@ -1382,6 +1382,78 @@ static int net_slirp_init(NetDriverState *nd)
return 0; return 0;
} }
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
{
const char *p, *p1;
int len;
p = *pp;
p1 = strchr(p, sep);
if (!p1)
return -1;
len = p1 - p;
p1++;
if (buf_size > 0) {
if (len > buf_size - 1)
len = buf_size - 1;
memcpy(buf, p, len);
buf[len] = '\0';
}
*pp = p1;
return 0;
}
static void net_slirp_redir(const char *redir_str)
{
int is_udp;
char buf[256], *r;
const char *p;
struct in_addr guest_addr;
int host_port, guest_port;
if (!slirp_inited) {
slirp_inited = 1;
slirp_init();
}
p = redir_str;
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
goto fail;
if (!strcmp(buf, "tcp")) {
is_udp = 0;
} else if (!strcmp(buf, "udp")) {
is_udp = 1;
} else {
goto fail;
}
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
goto fail;
host_port = strtol(buf, &r, 0);
if (r == buf)
goto fail;
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
goto fail;
if (buf[0] == '\0') {
pstrcpy(buf, sizeof(buf), "10.0.2.15");
}
if (!inet_aton(buf, &guest_addr))
goto fail;
guest_port = strtol(p, &r, 0);
if (r == p)
goto fail;
if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
fprintf(stderr, "qemu: could not set up redirection\n");
exit(1);
}
return;
fail:
fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
exit(1);
}
#endif /* CONFIG_SLIRP */ #endif /* CONFIG_SLIRP */
#if !defined(_WIN32) #if !defined(_WIN32)
@ -2334,7 +2406,9 @@ void help(void)
"-tun-fd fd use this fd as already opened tap/tun interface\n" "-tun-fd fd use this fd as already opened tap/tun interface\n"
#ifdef CONFIG_SLIRP #ifdef CONFIG_SLIRP
"-user-net use user mode network stack [default if no tap/tun script]\n" "-user-net use user mode network stack [default if no tap/tun script]\n"
"-tftp prefix allow tftp access to files starting with prefix [only with -user-net enabled]\n" "-tftp prefix allow tftp access to files starting with prefix [-user-net]\n"
"-redir [tcp|udp]:host-port:[guest-host]:guest-port\n"
" redirect TCP or UDP connections from host to guest [-user-net]\n"
#endif #endif
"-dummy-net use dummy network stack\n" "-dummy-net use dummy network stack\n"
"\n" "\n"
@ -2410,6 +2484,7 @@ enum {
QEMU_OPTION_tun_fd, QEMU_OPTION_tun_fd,
QEMU_OPTION_user_net, QEMU_OPTION_user_net,
QEMU_OPTION_tftp, QEMU_OPTION_tftp,
QEMU_OPTION_redir,
QEMU_OPTION_dummy_net, QEMU_OPTION_dummy_net,
QEMU_OPTION_kernel, QEMU_OPTION_kernel,
@ -2463,6 +2538,7 @@ const QEMUOption qemu_options[] = {
#ifdef CONFIG_SLIRP #ifdef CONFIG_SLIRP
{ "user-net", 0, QEMU_OPTION_user_net }, { "user-net", 0, QEMU_OPTION_user_net },
{ "tftp", HAS_ARG, QEMU_OPTION_tftp }, { "tftp", HAS_ARG, QEMU_OPTION_tftp },
{ "redir", HAS_ARG, QEMU_OPTION_redir },
#endif #endif
{ "dummy-net", 0, QEMU_OPTION_dummy_net }, { "dummy-net", 0, QEMU_OPTION_dummy_net },
@ -2756,14 +2832,14 @@ int main(int argc, char **argv)
break; break;
#ifdef CONFIG_SLIRP #ifdef CONFIG_SLIRP
case QEMU_OPTION_tftp: case QEMU_OPTION_tftp:
{
extern const char *tftp_prefix;
tftp_prefix = optarg; tftp_prefix = optarg;
} break;
break;
case QEMU_OPTION_user_net: case QEMU_OPTION_user_net:
net_if_type = NET_IF_USER; net_if_type = NET_IF_USER;
break; break;
case QEMU_OPTION_redir:
net_slirp_redir(optarg);
break;
#endif #endif
case QEMU_OPTION_dummy_net: case QEMU_OPTION_dummy_net:
net_if_type = NET_IF_DUMMY; net_if_type = NET_IF_DUMMY;