Commit 9bf05444b24f10616b9e9b9f296bcfdcba4ff0df
1 parent
a3504c87
port redirection support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1054 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
149 additions
and
9 deletions
Changelog
@@ -9,6 +9,7 @@ version 0.6.1: | @@ -9,6 +9,7 @@ version 0.6.1: | ||
9 | - VMware 3 and 4 read-only disk image support (untested) | 9 | - VMware 3 and 4 read-only disk image support (untested) |
10 | - Support for up to 4 serial ports | 10 | - Support for up to 4 serial ports |
11 | - TFTP server support (Magnus Damm) | 11 | - TFTP server support (Magnus Damm) |
12 | + - Port redirection support in user mode networking | ||
12 | 13 | ||
13 | version 0.6.0: | 14 | version 0.6.0: |
14 | 15 |
qemu-doc.texi
@@ -228,6 +228,44 @@ example of its use. | @@ -228,6 +228,44 @@ example of its use. | ||
228 | Use the user mode network stack. This is the default if no tun/tap | 228 | Use the user mode network stack. This is the default if no tun/tap |
229 | network init script is found. | 229 | network init script is found. |
230 | 230 | ||
231 | +@item -tftp prefix | ||
232 | +When using the user mode network stack, activate a built-in TFTP | ||
233 | +server. All filenames beginning with @var{prefix} can be downloaded | ||
234 | +from the host to the guest using a TFTP client. The TFTP client on the | ||
235 | +guest must be configured in binary mode (use the command @code{bin} of | ||
236 | +the Unix TFTP client). The host IP address on the guest is as usual | ||
237 | +10.0.2.2. | ||
238 | + | ||
239 | +@item -redir [tcp|udp]:host-port:[guest-host]:guest-port | ||
240 | + | ||
241 | +When using the user mode network stack, redirect incoming TCP or UDP | ||
242 | +connections to the host port @var{host-port} to the guest | ||
243 | +@var{guest-host} on guest port @var{guest-port}. If @var{guest-host} | ||
244 | +is not specified, its value is 10.0.2.15 (default address given by the | ||
245 | +built-in DHCP server). | ||
246 | + | ||
247 | +For example, to redirect host X11 connection from screen 1 to guest | ||
248 | +screen 0, use the following: | ||
249 | + | ||
250 | +@example | ||
251 | +# on the host | ||
252 | +qemu -redir tcp:6001::6000 [...] | ||
253 | +# this host xterm should open in the guest X11 server | ||
254 | +xterm -display :1 | ||
255 | +@end example | ||
256 | + | ||
257 | +To redirect telnet connections from host port 5555 to telnet port on | ||
258 | +the guest, use the following: | ||
259 | + | ||
260 | +@example | ||
261 | +# on the host | ||
262 | +qemu -redir tcp:5555::23 [...] | ||
263 | +telnet localhost 5555 | ||
264 | +@end example | ||
265 | + | ||
266 | +Then when you use on the host @code{telnet localhost 5555}, you | ||
267 | +connect to the guest telnet server. | ||
268 | + | ||
231 | @item -dummy-net | 269 | @item -dummy-net |
232 | Use the dummy network stack: no packet will be received by the network | 270 | Use the dummy network stack: no packet will be received by the network |
233 | cards. | 271 | cards. |
@@ -652,7 +690,12 @@ Note that @code{ping} is not supported reliably to the internet as it | @@ -652,7 +690,12 @@ Note that @code{ping} is not supported reliably to the internet as it | ||
652 | would require root priviledges. It means you can only ping the local | 690 | would require root priviledges. It means you can only ping the local |
653 | router (10.0.2.2). | 691 | router (10.0.2.2). |
654 | 692 | ||
655 | -The user mode network is currently only supported on a Unix host. | 693 | +When using the built-in TFTP server, the router is also the TFTP |
694 | +server. | ||
695 | + | ||
696 | +When using the @option{-redir} option, TCP or UDP connections can be | ||
697 | +redirected from the host to the guest. It allows for example to | ||
698 | +redirect X11, telnet or SSH connections. | ||
656 | 699 | ||
657 | @node direct_linux_boot | 700 | @node direct_linux_boot |
658 | @section Direct Linux Boot | 701 | @section Direct Linux Boot |
slirp/libslirp.h
@@ -3,8 +3,10 @@ | @@ -3,8 +3,10 @@ | ||
3 | 3 | ||
4 | #ifdef _WIN32 | 4 | #ifdef _WIN32 |
5 | #include <winsock2.h> | 5 | #include <winsock2.h> |
6 | +int inet_aton(const char *cp, struct in_addr *ia); | ||
6 | #else | 7 | #else |
7 | #include <sys/select.h> | 8 | #include <sys/select.h> |
9 | +#include <arpa/inet.h> | ||
8 | #endif | 10 | #endif |
9 | 11 | ||
10 | void slirp_init(void); | 12 | void slirp_init(void); |
@@ -20,4 +22,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len); | @@ -20,4 +22,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len); | ||
20 | int slirp_can_output(void); | 22 | int slirp_can_output(void); |
21 | void slirp_output(const uint8_t *pkt, int pkt_len); | 23 | void slirp_output(const uint8_t *pkt, int pkt_len); |
22 | 24 | ||
25 | +int slirp_redir(int is_udp, int host_port, | ||
26 | + struct in_addr guest_addr, int guest_port); | ||
27 | + | ||
28 | +extern const char *tftp_prefix; | ||
29 | + | ||
23 | #endif | 30 | #endif |
slirp/slirp.c
@@ -617,3 +617,18 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) | @@ -617,3 +617,18 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) | ||
617 | memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); | 617 | memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); |
618 | slirp_output(buf, ip_data_len + ETH_HLEN); | 618 | slirp_output(buf, ip_data_len + ETH_HLEN); |
619 | } | 619 | } |
620 | + | ||
621 | +int slirp_redir(int is_udp, int host_port, | ||
622 | + struct in_addr guest_addr, int guest_port) | ||
623 | +{ | ||
624 | + if (is_udp) { | ||
625 | + if (!udp_listen(htons(host_port), guest_addr.s_addr, | ||
626 | + htons(guest_port), 0)) | ||
627 | + return -1; | ||
628 | + } else { | ||
629 | + if (!solisten(htons(host_port), guest_addr.s_addr, | ||
630 | + htons(guest_port), 0)) | ||
631 | + return -1; | ||
632 | + } | ||
633 | + return 0; | ||
634 | +} |
slirp/tftp.c
@@ -36,7 +36,7 @@ struct tftp_session { | @@ -36,7 +36,7 @@ struct tftp_session { | ||
36 | 36 | ||
37 | struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; | 37 | struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; |
38 | 38 | ||
39 | -char *tftp_prefix; | 39 | +const char *tftp_prefix; |
40 | 40 | ||
41 | static void tftp_session_update(struct tftp_session *spt) | 41 | static void tftp_session_update(struct tftp_session *spt) |
42 | { | 42 | { |
slirp/tftp.h
vl.c
@@ -1382,6 +1382,78 @@ static int net_slirp_init(NetDriverState *nd) | @@ -1382,6 +1382,78 @@ static int net_slirp_init(NetDriverState *nd) | ||
1382 | return 0; | 1382 | return 0; |
1383 | } | 1383 | } |
1384 | 1384 | ||
1385 | +static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) | ||
1386 | +{ | ||
1387 | + const char *p, *p1; | ||
1388 | + int len; | ||
1389 | + p = *pp; | ||
1390 | + p1 = strchr(p, sep); | ||
1391 | + if (!p1) | ||
1392 | + return -1; | ||
1393 | + len = p1 - p; | ||
1394 | + p1++; | ||
1395 | + if (buf_size > 0) { | ||
1396 | + if (len > buf_size - 1) | ||
1397 | + len = buf_size - 1; | ||
1398 | + memcpy(buf, p, len); | ||
1399 | + buf[len] = '\0'; | ||
1400 | + } | ||
1401 | + *pp = p1; | ||
1402 | + return 0; | ||
1403 | +} | ||
1404 | + | ||
1405 | +static void net_slirp_redir(const char *redir_str) | ||
1406 | +{ | ||
1407 | + int is_udp; | ||
1408 | + char buf[256], *r; | ||
1409 | + const char *p; | ||
1410 | + struct in_addr guest_addr; | ||
1411 | + int host_port, guest_port; | ||
1412 | + | ||
1413 | + if (!slirp_inited) { | ||
1414 | + slirp_inited = 1; | ||
1415 | + slirp_init(); | ||
1416 | + } | ||
1417 | + | ||
1418 | + p = redir_str; | ||
1419 | + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | ||
1420 | + goto fail; | ||
1421 | + if (!strcmp(buf, "tcp")) { | ||
1422 | + is_udp = 0; | ||
1423 | + } else if (!strcmp(buf, "udp")) { | ||
1424 | + is_udp = 1; | ||
1425 | + } else { | ||
1426 | + goto fail; | ||
1427 | + } | ||
1428 | + | ||
1429 | + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | ||
1430 | + goto fail; | ||
1431 | + host_port = strtol(buf, &r, 0); | ||
1432 | + if (r == buf) | ||
1433 | + goto fail; | ||
1434 | + | ||
1435 | + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) | ||
1436 | + goto fail; | ||
1437 | + if (buf[0] == '\0') { | ||
1438 | + pstrcpy(buf, sizeof(buf), "10.0.2.15"); | ||
1439 | + } | ||
1440 | + if (!inet_aton(buf, &guest_addr)) | ||
1441 | + goto fail; | ||
1442 | + | ||
1443 | + guest_port = strtol(p, &r, 0); | ||
1444 | + if (r == p) | ||
1445 | + goto fail; | ||
1446 | + | ||
1447 | + if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { | ||
1448 | + fprintf(stderr, "qemu: could not set up redirection\n"); | ||
1449 | + exit(1); | ||
1450 | + } | ||
1451 | + return; | ||
1452 | + fail: | ||
1453 | + fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n"); | ||
1454 | + exit(1); | ||
1455 | +} | ||
1456 | + | ||
1385 | #endif /* CONFIG_SLIRP */ | 1457 | #endif /* CONFIG_SLIRP */ |
1386 | 1458 | ||
1387 | #if !defined(_WIN32) | 1459 | #if !defined(_WIN32) |
@@ -2334,7 +2406,9 @@ void help(void) | @@ -2334,7 +2406,9 @@ void help(void) | ||
2334 | "-tun-fd fd use this fd as already opened tap/tun interface\n" | 2406 | "-tun-fd fd use this fd as already opened tap/tun interface\n" |
2335 | #ifdef CONFIG_SLIRP | 2407 | #ifdef CONFIG_SLIRP |
2336 | "-user-net use user mode network stack [default if no tap/tun script]\n" | 2408 | "-user-net use user mode network stack [default if no tap/tun script]\n" |
2337 | - "-tftp prefix allow tftp access to files starting with prefix [only with -user-net enabled]\n" | 2409 | + "-tftp prefix allow tftp access to files starting with prefix [-user-net]\n" |
2410 | + "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" | ||
2411 | + " redirect TCP or UDP connections from host to guest [-user-net]\n" | ||
2338 | #endif | 2412 | #endif |
2339 | "-dummy-net use dummy network stack\n" | 2413 | "-dummy-net use dummy network stack\n" |
2340 | "\n" | 2414 | "\n" |
@@ -2410,6 +2484,7 @@ enum { | @@ -2410,6 +2484,7 @@ enum { | ||
2410 | QEMU_OPTION_tun_fd, | 2484 | QEMU_OPTION_tun_fd, |
2411 | QEMU_OPTION_user_net, | 2485 | QEMU_OPTION_user_net, |
2412 | QEMU_OPTION_tftp, | 2486 | QEMU_OPTION_tftp, |
2487 | + QEMU_OPTION_redir, | ||
2413 | QEMU_OPTION_dummy_net, | 2488 | QEMU_OPTION_dummy_net, |
2414 | 2489 | ||
2415 | QEMU_OPTION_kernel, | 2490 | QEMU_OPTION_kernel, |
@@ -2463,6 +2538,7 @@ const QEMUOption qemu_options[] = { | @@ -2463,6 +2538,7 @@ const QEMUOption qemu_options[] = { | ||
2463 | #ifdef CONFIG_SLIRP | 2538 | #ifdef CONFIG_SLIRP |
2464 | { "user-net", 0, QEMU_OPTION_user_net }, | 2539 | { "user-net", 0, QEMU_OPTION_user_net }, |
2465 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, | 2540 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, |
2541 | + { "redir", HAS_ARG, QEMU_OPTION_redir }, | ||
2466 | #endif | 2542 | #endif |
2467 | { "dummy-net", 0, QEMU_OPTION_dummy_net }, | 2543 | { "dummy-net", 0, QEMU_OPTION_dummy_net }, |
2468 | 2544 | ||
@@ -2756,14 +2832,14 @@ int main(int argc, char **argv) | @@ -2756,14 +2832,14 @@ int main(int argc, char **argv) | ||
2756 | break; | 2832 | break; |
2757 | #ifdef CONFIG_SLIRP | 2833 | #ifdef CONFIG_SLIRP |
2758 | case QEMU_OPTION_tftp: | 2834 | case QEMU_OPTION_tftp: |
2759 | - { | ||
2760 | - extern const char *tftp_prefix; | ||
2761 | tftp_prefix = optarg; | 2835 | tftp_prefix = optarg; |
2762 | - } | ||
2763 | - break; | 2836 | + break; |
2764 | case QEMU_OPTION_user_net: | 2837 | case QEMU_OPTION_user_net: |
2765 | net_if_type = NET_IF_USER; | 2838 | net_if_type = NET_IF_USER; |
2766 | break; | 2839 | break; |
2840 | + case QEMU_OPTION_redir: | ||
2841 | + net_slirp_redir(optarg); | ||
2842 | + break; | ||
2767 | #endif | 2843 | #endif |
2768 | case QEMU_OPTION_dummy_net: | 2844 | case QEMU_OPTION_dummy_net: |
2769 | net_if_type = NET_IF_DUMMY; | 2845 | net_if_type = NET_IF_DUMMY; |